使用vite打包单个组件和直接使用浏览器打开打包的方式
这篇文章主要分享一下vite打包两种方式
- vite打包支持浏览器直接打开
- 使用vite打包单个组件并发布到npm
由于都属于vite打包相关就将其整合到一篇文章中了,有相关需求的朋友可直接查看对应章节即可
vite打包支持浏览器直接打开
最近遇到一个需求,为公司客户端写一个pdf打印模块。由于客户端同事坚持要使用静态文件的方式打开。。。那没办法,我得满足他
- 配置base为./相对路径
import { UserConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default ({ mode }): UserConfig => {
return {
base: mode === 'development' ? '/' : './',
plugins: [vue()]
}
}
可是打包后打开直接用index.html页面却呈现出空白状态,我小心翼翼打开控制台发现是跨域问题
官方给出的解释是你得起个服务 cn.vitejs.dev/guide/troub…
无奈,只能另寻它法
方式一:将所有资源打包到index.html中
使用vite-plugin-singlefile插件将所有资源打包到index.html
- 安装插件
npm i vite-plugin-singlefile -D
- 修改vite.config.ts配置
import { UserConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { viteSingleFile } from 'vite-plugin-singlefile'
// https://vitejs.dev/config/
export default ({ mode }): UserConfig => {
return {
base: mode === 'development' ? '/' : './',
plugins: [vue(), viteSingleFile()]
}
}
缺陷:项目过大会导致index.html越大,加载很慢,用不用视情况而定
方式二:这也是作者推荐的方式
- 使用@vitejs/plugin-legacy为打包后的文件提供传统浏览器兼容性支持
npm i @vitejs/plugin-legacy terser -D
- 配置vite.config.ts
import { UserConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import legacy from '@vitejs/plugin-legacy'
// https://vitejs.dev/config/
export default ({ mode }): UserConfig => {
return {
base: mode === 'development' ? '/' : './',
plugins: [
vue(),
legacy({
targets: ['defaults', 'not IE 11']
})
]
}
}
- npm run build 打包后将index.html中所有的 标签中的 type="module"、crossorigin、nomodule 移除
<script type="module" crossorigin src="./assets/index-993358c3.js"></script>
<script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-2fc23d6e.js"></script>
<!-- 移除后 -->
<script src="./assets/index-993358c3.js"></script>
<script id="vite-legacy-polyfill" src="./assets/polyfills-legacy-2fc23d6e.js"></script>
- 手动替换显然不是明智之举,我们可以写个脚本,运行完打包后再运行脚本替换
// scripts/build.cjs
const fs = require('fs')
const path = require('path')
const srcDir = path.resolve(__dirname, '../dist')
function mian() {
const url = path.join(srcDir, 'index.html')
// 读取dist/index.html
let htmlStr = fs.readFileSync(url, { encoding: 'utf-8' })
// 匹配script标签
const reg = /<script.*>/g
htmlStr = htmlStr.replace(reg, (str) => {
// 替换关键字
return str.replace(/\snomodule|\scrossorigin|\stype="module"/g, '')
})
// 输出文件
fs.writeFileSync(url, htmlStr)
}
mian()
- 修改package.json打包命令
{
"scripts": {
"build": "vue-tsc && vite build && node ./scripts/build.cjs",
}
}
- 运行 npm run build 查看效果
使用vite打包单个组件并发布到npm
前段时间写了两个独立的vue组件,es-drager拖拽组件、es-calendar日历组件,这里记录一下使用vite打包单个组件的方式
- 支持单文件引入
- 支持script标签方式引入
- 支持ts类型提示
关于组件库的打包以及如何开发vue3组件库请参考我的这篇文章 手把手从零搭建一个 vue3 组件库 (一)
组件准备
- drager组件 src/drager/drager.vue
<template>
<div class="es-drager"></div>
</template>
<script setup lang="ts"></script>
<style scoped>
.es-drager {
width: 100px;
height: 100px;
border: 1px solid red;
}
</style>
- 导出组件,添加install方法
// src/drager/index.ts
import { App, Plugin } from 'vue'
import Drager from './drager.vue'
export const install = (app: App) => {
app.component('es-drager', Drager)
}
Drager.install = install
export {
Drager as ESDrager
}
export default Drager as Plugin & typeof Drager
- src/vite-env.d.ts
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
打包配置
- 安装 vite-plugin-dts
npm i vite-plugin-dts -D
vite.config.ts配置
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import dts from 'vite-plugin-dts'
import { resolve } from 'path'
export default defineConfig({
plugins: [dts(), vue()],
build: {
outDir: 'lib',
lib: {
entry: resolve(__dirname, './src/drager/index.ts'),
name: 'ESDrager', // 使用script标签引入时全局名称
fileName: format => `index.${format}.js`,
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['vue'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: 'Vue'
}
}
}
}
})
vite库模式默认支持es 和 umd格式,根据需求可自行修改
package.json 配置,参考 cn.vitejs.dev/guide/build…
// package.json
{
"name": "es-drager",
"version": "0.0.0",
"files": [
"lib" // 将lib目录发布到npm
],
"main": "./lib/index.umd.js", // script标签引入umd
"module": "./lib/index.es.js", // 单文件引入
"exports": {
".": {
"import": "./lib/index.es.js",
"require": "./lib/index.umd.js"
},
"./*": "./*"
},
"typings": "lib/drager/index.d.ts", // ts类型声明文件
// ... 其它配置
}
-
typings 设置打包后的类型声明入口文件
-
相对路径导入,例如导入样式:
import 'es-drager/lib/style.css'
,如果没有配置在vite项目中会报错
{
"exports": {
"./*": "./*"
},
}
添加发布脚本
{
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"release": "npm run build && npm publish", // 新增
"preview": "vite preview"
}
}
运行 npm run release打包并发布
完整package.json配置
{
"name": "es-drager",
"version": "0.2.9",
"description": "A drag、resizable、rotatable component based on vue3",
"keywords": [
"drag",
"resize",
"rotate",
"vue-drager",
"vue-drag-resize",
"vue-drager",
"es-drager"
],
"homepage": "https://github.com/vangleer/es-drager",
"bugs": {
"url": "https://github.com/vangleer/es-drager/issues"
},
"license": "MIT",
"author": "vangleer",
"files": [
"lib"
],
"main": "./lib/index.umd.js",
"module": "./lib/index.es.js",
"exports": {
".": {
"import": "./lib/index.es.js",
"require": "./lib/index.umd.js"
},
"./*": "./*"
},
"repository": {
"type": "git",
"url": "https://github.com/vangleer/es-drager.git"
},
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"release": "npm run build && npm publish",
"preview": "vite preview"
},
"dependencies": {
"es-drager": "^0.2.8",
"vue": ">=3.2.0"
},
"devDependencies": {
"@types/node": "^18.15.13",
"@vitejs/plugin-vue": "^4.1.0",
"typescript": "^4.9.3",
"vite": "^4.2.0",
"vite-plugin-dts": "^2.3.0",
"vue-tsc": "^1.2.0"
},
"peerDependencies": {
"vue": ">=3.2.0"
},
"typings": "lib/drager/index.d.ts"
}
使用说明
全局注册
import { createApp } from 'vue'
import App from './App.vue'
import 'es-drager/dist/style.css'
import Drager from 'es-drager'
createApp(App)
.component('es-drager', Drager)
.mount('#app')
- 使用
<template>
<es-drager>
drager
</es-drager>
</template>
组件中直接使用
<template>
<Drager>
drager
</Drager>
</template>
<script setup lang='ts'>
import Drager from 'es-drager'
</script>
浏览器直接引入
直接通过浏览器的 HTML 标签导入 es-drager,然后就可以使用全局变量 ESDrager 了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/es-drager/lib/style.css">
<title>Document</title>
</head>
<body>
<div id="app">
<es-drager>drager</es-drager>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/es-drager"></script>
<script>
const { createApp } = Vue
const app = createApp({})
app.use(ESDrager)
app.mount('#app')
</script>
</body>
</html>
转载自:https://juejin.cn/post/7237240999243694117