背景

最近,就 前端开发过程中的痛点及可优化项 做了一次收集。 其中,构建耗时、我的项目编译速度慢 的字眼呈现了好几次。

随着业务的疾速倒退,咱们很多我的项目的体积也疾速收缩。 随之而来的, 就是打包变慢等问题。

晋升研发效率,是技术人永恒的谋求。

咱们我的项目也有启动慢的问题,共事也提到过几次。 刚好我之前也做过相似的摸索和优化, 于是就借这个机会,革新一下我的项目, 解决启动耗时的问题

于昨天下午(2021.4.7 23:00), 胜利嵌入 Vite, 我的项目启动工夫由约 190s => 20s, 热更新工夫缩短为 2s

两头踩了一些坑, 好在最初爬出来了, 相干技术要点都会在下文中出现。

FBI Warning: 以下文字,只是我联合本人的理论我的项目, 总结进去的一些肤浅的教训, 如有谬误,欢送斧正 :)

明天的次要内容:

  • 为什么 Vite 启动这么快
  • 我的我的项目如何植入 Vite
  • 我在革新过程中遇到的问题
  • 对于 Vite 开发、打包上线的一些思考
  • 相干代码和论断

注释

为什么 Vite 启动这么快

底层实现上, Vite 是基于 esbuild 预构建依赖的。

esbuild 应用 go 编写,并且比以 js 编写的打包器预构建依赖, 快 10 - 100 倍。

因为 js 跟 go 相比切实是太慢了,js 的个别操作都是毫秒计,go 则是纳秒。

另外, 两者的启动形式也有所差别。

webpack 启动形式

Vite 启动形式

Webpack 会先打包,而后启动开发服务器,申请服务器时间接给予打包后果。

而 Vite 是间接启动开发服务器,申请哪个模块再对该模块进行实时编译

因为古代浏览器自身就反对 ES Module,会主动向依赖的 Module 发出请求。

Vite 充分利用了这一点,将开发环境下的模块文件,就作为浏览器要执行的文件,而不是像 W ebpack 那样进行打包合并

因为 Vite 在启动的时候不须要打包,也就意味着不须要剖析模块的依赖不须要编译
因而启动速度十分快。当浏览器申请某个模块时,再依据须要对模块内容进行编译。

这种按需动静编译的形式,极大的缩减了编译工夫,我的项目越简单、模块越多,vite 的劣势越显著。

在 HMR(热更新)方面,当改变了一个模块后,仅需让浏览器从新申请该模块即可,不像webpack那样须要把该模块的相干依赖模块全副编译一次,效率更高。

从理论的开发体验来看, 在 Vite 模式下, 开发环境能够霎时启动, 然而等到页面进去, 要等一段时间。

我的我的项目如何植入 Vite

新我的项目

创立一个 Vite 新我的项目就比较简单:

yarn create @vitejs/app

生成好之后, 间接启动就能够了:

已有我的项目

已有我的项目的迁徙, 略微繁琐一些。

首先, 退出 Vite 的相干配置。 这里我应用了一个 cli 工具: wp2vite.

装置好之后, 间接执行:

这一步, 会主动生成 Vite 的配置文件,并引入相干的依赖。

把依赖装置一下, 启动就能够了。

如果没有意外的话, 你会播种一堆报错

祝贺你,进入开心欢快的踩坑环节。

我在革新过程中遇到的问题

1. alias 谬误

我的项目代码里配置了一些别名,vite 无奈辨认,所以须要在vite 外面也配置 alias:

  resolve: {    alias: {      '@': resolve(__dirname, 'src'),    },  },

2. 无奈辨认 less 全局变量

解决办法:

把自定义的全局变量从内部注入即可, 间接在 vite.config.js 的 css 选项中退出:

  css: {    preprocessorOptions: {      less: {        modifyVars: {          hack: `true;@import '${resolve('./src/vars.less')}';`,          ...themeVariables,        },        javascriptEnabled: true,      },    },  },

3. Uncaught Error: Target container is not a DOM element.

根元素未找到。

起因是: 默认生成的 index.html 中:

<div id="root"></div>

id 是 root, 而逻辑中的是#app, 这里间接改成 id=app 即可。

4. typings 文件找不到

typings 文件未找到

这个谬误, 乍一看, 一头雾水。

进去看一下源代码和编译后的代码:

源代码:

编译后:

typings 文件这不是好好的在这吗, 怎么就找不到?

想了一下: Vite 不晓得 typeings 文件是不须要被编译的,须要通知编译器不编译这个文件。

最初在 TS 官网文档里找到了答案:

https://www.typescriptlang.or...

Type-Only Imports and Export

This feature is something most users may never have to think about; however, if you’ve hit issues under --isolatedModules, TypeScript’s transpileModule API, or Babel, this feature might be relevant.

TypeScript 3.8 adds a new syntax for type-only imports and exports.

import type { SomeThing } from "./some-module.js";export type { SomeThing };

须要独自引入types, 于是把代码改为:

同时要留神, 如果一个文件有有多个导出, 也要离开引入:

惟一苦楚的是: 全局都须要改一遍, 体力活。

至此,typeings 问题完满解决。

5. 无奈辨认 svg

咱们在应用 svg 作为图标组件的时候, 个别是:

import Icon from '@ant-design/icons';import ErrorSvg from '@/assets/ico_error.svg';const ErrorIcon = (props: any) => <Icon component={ErrorSvg} />;// ...<ErrorIcon />

浏览器报错:

error occurred in the </src/assets/ico_error.svg> component

很显著的看到, 这里是把文件门路作为组件了。

当初要做的是:把这个文件门路, 换成能够辨认的组件。

搜寻一番, 找到了个插件: vite-plugin-react-svg

退出配置:

const reactSvgPlugin = require('vite-plugin-react-svg');plugins: [  reactSvgPlugin(),],
import MyIcon from './svgs/my-icon.svg?component';function App() {  return (    <div>      <MyIcon />    </div>  );}

须要留神的是: 引入的 svg 文件须要加 ?component 作为后缀。

看了一下源码, 这个后缀是用来作为标识符的,

如果后缀匹配上是component, 就解析文件, 并缓存, 最初返回后果:

晓得原理之后, 就须要把全副的 .svg => .svg?component

vscode 一键替换就能够, 不过留神别把 node_module 外面的也替换了。

6. global 未定义

global 是 Node外面的变量, 会在客户端报错 ?

一层层看上来, 原来是引入的第三方包应用了global。

看 vite 文档里提到了 Client Types:

追加到 tsconfig 外面:

 "compilerOptions": {    "types": ["node", "jest", "vite/client"], }

而后, 并没有什么乱用。。。

没方法, 只得祭出 window 大法。

在入口index.tsx 外面加上:

(window as any).global = window;

刷新, 好了。

7. [未解决] 代替HtmlWebpackPlugin

还须要注入一些内部变量, 批改入口html, favicon, title 之类。

找到一个插件: vite-plugin-singlefile

不过并没有什么用。

有理解的同学请留言赐教。

至此, 整个app 曾经能在本地跑起来了, build 也没问题。

7. 线上打包构建时, 内存溢出

本地能跑起来, 打包也没问题, 前面当然是放到线上跑一跑啦。

立即安顿!

内存不足, 我就给你加点:

搞定!

对于 Vite 开发、打包上线的一些思考

从理论应用来看, vite 在一些性能上还是无奈齐全代替 webpack。

毕竟是后起之秀, 相干的生态还须要继续欠缺。

集体认为,目前一种比拟稳当的形式是:

  • 保留 webpack dev & build 的能力, vite 仅作为开发的辅助

等相干工具再欠缺一些, 再思考齐全迁徙过去。

相干代码和论断

一个残缺的 Vite demo

仓库地址: https://github.com/beMySun/re...

业务我的项目的 vite.config.js 残缺配置

import { defineConfig } from 'vite';import reactRefresh from '@vitejs/plugin-react-refresh';import legacyPlugin from '@vitejs/plugin-legacy';import { resolve } from 'path';const fs = require('fs');const lessToJS = require('less-vars-to-js');const themeVariables = lessToJS(fs.readFileSync(resolve(__dirname, './src/antd-custom.less'), 'utf8'));const reactSvgPlugin = require('vite-plugin-react-svg');// https://cn.vitejs.dev/config/export default defineConfig({  base: './',  root: './',  resolve: {    alias: {      'react-native': 'react-native-web',      '@': resolve(__dirname, 'src'),    },  },  define: {    'process.env.REACT_APP_IS_LOCAL': '\'true\'',    'window.__CID__': JSON.stringify(process.env.cid || 'id'),  },  server: {    port: 8080,    proxy: {      '/api': {        target: 'https://stoku.test.shopee.co.id/',        changeOrigin: true,        cookieDomainRewrite: {          'stoku.test.shopee.co.id': 'localhost',        },      },    },  },  build: {    target: 'es2015',    minify: 'terser',    manifest: false,    sourcemap: false,    outDir: 'build',    rollupOptions: {},  },  esbuild: {},  optimizeDeps: {},  plugins: [    // viteSingleFile({    //   title: 'dynamic title', // doesn't work    // }),    reactSvgPlugin(),    reactRefresh(),    legacyPlugin({      targets: [        'Android > 39',        'Chrome >= 60',        'Safari >= 10.1',        'iOS >= 10.3',        'Firefox >= 54',        'Edge >= 15',      ],    }),    // vitePluginImp({    //   libList: [    //     {    //       libName: 'antd',    //       style: (name) => `antd/es/${name}/style`,    //     },    //   ],    // }),  ],  css: {    preprocessorOptions: {      less: {        modifyVars: {          hack: `true;@import '${resolve('./src/vars.less')}';`,          ...themeVariables,        },        javascriptEnabled: true,      },    },  },});

最初

应用 Vite 能大幅缩短我的项目构建工夫,晋升开发效率。

不过也要联合我的项目的理论状况,正当取舍。

对于我的这个我的项目而言,把 Vite 作为辅助开发的一种形式,还是挺有用的。

期待 Vite 能持续欠缺,为研发提效。

好了, 内容大略就这么多, 心愿对大家有所帮忙。

满腹经纶,如有谬误, 欢送斧正。

谢谢。

最初,如果感觉内容有帮忙, 能够关注下我的公众号,把握最新动静,一起学习!