Vite2 实践

527 阅读4分钟

据说Vite速度很快,正好有个H5的新项目,实践一下吧,以下是基于Vite2.6.4

一、兼容性

Vite打包后的文件是ESModule格式的,需要浏览器对原生ESModule支持,可以通过build.target指定构建目标,最低支持es2015

移动端webview基于webkit的内核,高版本对原生ESModule的支持没问题。低版本可以通过插件@vitejs/plugin-legacy来支持,可以大胆使用啦

二、对比webpack的一些优势

  1. 启动速度快:vite启动项目时是直接启动,需要哪个模块再请求对应模块并实时编译,主要利用现代浏览器对ESModule的原生支持,所以启动很快
  2. 热更新速度快:热更新时只重新请求需要更新模块
  3. 内置支持TS
  4. 插件兼容rollup的插件接口,可以采用rollup插件
  5. 打包后的资源很简洁,干净

三、配置

 详细配置可以参考: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报错: image.png 查看打包后的vendor.js,有如下代码 image.png

  • IOS12下报错: image.png

  • OPPO安卓8 不支持import,动态导入的legacy文件script标签上有crossorigin="anonymous"属性,加载文件时报 跨域错误

使用 terser压缩之后,上面所述报错没有了。但是IOS11系统下报了上面IOS12下的错误。只能在页面直接引入polyfills-legacy文件了。

四、插件

Vite扩展了rollup的插件接口,可以使用兼容的rollup插件

官方提供的Vite专属插件和兼容的rollup插件,如下

github.com/vitejs/awes…

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生成的资源