据说Vite速度很快,正好有个H5的新项目,实践一下吧,以下是基于Vite2.6.4
一、兼容性
Vite打包后的文件是ESModule格式的,需要浏览器对原生ESModule支持,可以通过build.target指定构建目标,最低支持es2015
移动端webview基于webkit的内核,高版本对原生ESModule的支持没问题。低版本可以通过插件@vitejs/plugin-legacy来支持,可以大胆使用啦
二、对比webpack的一些优势
- 启动速度快:vite启动项目时是直接启动,需要哪个模块再请求对应模块并实时编译,主要利用现代浏览器对ESModule的原生支持,所以启动很快
- 热更新速度快:热更新时只重新请求需要更新模块
- 内置支持TS
- 插件兼容rollup的插件接口,可以采用rollup插件
- 打包后的资源很简洁,干净
三、配置
详细配置可以参考:cn.vitejs.dev/config/
下面列出一些常用但是文档里写的不详细的
1. 静态资源分类
默认打包后的文件直接放在assets文件下了,没按静态资源类型分文件夹,可以进行如下配置,对文件分类
export default defineConfig(({ command, mode}) => {
return {
build: {
rollupOptions: {
output: {
entryFileNames: `assets/js/[name].js`,
chunkFileNames: `assets/js/[name].js`,
assetFileNames: `assets/[ext]/[name].[ext]`
}
}
}
}
})
2. 配置全局的scss变量
多处用到的一些scss变量,如果每次用都需要引入比较麻烦,可以全局配置
export default defineConfig(({ command, mode}) => {
return {
css: {
preprocessorOptions: {
scss: { // 配置全局的scss变量
additionalData: '@import "./src/assets/css/common.scss"; @import "./public/css/common.scss";'
}
}
}
}
})
3.静态资源包过大
当引入组件过多时,比如swiper,echarts,react, react-dom。会全部打包到vendor里,压缩后还有700多K,可以在build-> rollupOptions -> output 里面加上 manualChunks, 分割代码
output: {
manualChunks: {
swiper: ['swiper'],
echarts: ['echarts'],
react: ['react', 'react-dom']
},
},
4.是否压缩静态资源
可以通过build -> minify 来配置是否混淆静态资源,采用哪种方式混淆,默认采用的esbuild,速度快,但是实际使用中IOS11, IOS12,OPPO安卓8报错。采用terser混淆,兼容性更好。也可以配置minify为false,方便测试环境查看代码
build: {
minify: 'terser'
}
-
IOS11报错:
查看打包后的vendor.js,有如下代码
-
IOS12下报错:
-
OPPO安卓8 不支持import,动态导入的legacy文件script标签上有crossorigin="anonymous"属性,加载文件时报 跨域错误
使用 terser压缩之后,上面所述报错没有了。但是IOS11系统下报了上面IOS12下的错误。只能在页面直接引入polyfills-legacy文件了。
四、插件
Vite扩展了rollup的插件接口,可以使用兼容的rollup插件
官方提供的Vite专属插件和兼容的rollup插件,如下
vite-rollup-plugins.patak.dev/
如果没有满足自己需求的,还可以自己开发,具体API可以参考 cn.vitejs.dev/guide/api-p…
就是一个带有带有特定钩子的函数, 例如
const htmlPlugin = () => {
return {
name: 'vite:html',
transformIndexHtml(html){
return html.replace(....)
}
}
}
transformIndexHtml 是转换html 专用的钩子,在转换html时,发现很多插件都是对html中特殊字符进行替换,或者向html中插入内容
执行这个钩子时,是遍历所有钩子后,再执行插入操作,如果想对一个插件插入的内容进行匹配删除,这个钩子就没法实现
五、实践中遇到的问题
1. ESModule文件 不支持file协议访问
打包后的html如果http或者https协议访问,静态资源路径同样协议或者相对路径访问都可以,但是html如果用file:// 协议打开,就会报错,原因就是ESModule文件不支持file协议访问
如下,html地址,静态资源路径两种写法都可以没问题
// html地址
<http://dev.xxx.cn/dest/src/pages/picture/index.html>
<script type="module" crossorigin src="http://test.xxx/ssfe/xxx/assets/js/picture.js"></script>
<script type="module" crossorigin src="../../../assets/js/picture.js"></script>
用file:// 协议打开html,静态资源用相对路径就会出现如下提示
// file协议访问
file:///Users/xxx/Documents/git/app/xxx/dest/src/pages/picture/index.html
// 报错
Access to script at 'file:///Users/xxx/Documents/git/app/xxx/dest/assets/js/picture.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
如果html和静态资源需要放在本地,就需要删除ESModule的静态资源,只用兼容ES5生成的资源