第 122 题:webpack 打包 vue 速度太慢怎么办?
项目使用 ts+webpack+vue,发现了 npm 跑起来和打包起来都非常的慢,经过多番查阅,发现是一个配置得问题
Webpack 配置 TS 和 TSLint 支持
{
test: /\.tsx*?$/,
exclude: /node_modules/,
loader: require.resolve('ts-loader'),
options: {
transpileOnly: true,
},
}
需要注意的是 options 处设置了 transpileOnly 为 true,否则编译会很慢很慢,官方解释是:
As your project becomes bigger and bigger, compilation time increases linearly. It’s because typescript’s semantic checker has to inspect all files on every rebuild. The simple solution is to disable it by using the transpileOnly: true option, but doing so leaves you without type checking.
也就是每次都要跑一边类型检查
注意最后一句话,那如果我们还想要 type checking 怎么办呢?后面接着就解释怎么做了,想看原文的话去 ts-loader 的 GitHub 库看就好了。我就说下是怎么做的。
你需要配置下这个插件 fork-ts-checker-webpack-plugin:
new ForkTsCheckerWebpackPlugin({
checkSyntacticErrors: true,
tsconfig: path.resolve(__dirname, 'tsconfig.json'),
tslint: path.resolve(__dirname, 'tslint.json'),
watch: ['./src/**/*.tsx'],
ignoreLints: [
'no-console',
'object-literal-sort-keys',
'quotemark',
],
})
把他加入到 Webpack 的 Plugins 中去,然后在 Webpack 启动时他会自动创建一个新进程去做 type checking,和 Webpack 的编译独立开来了,这样就可以在快速编译的同时又可以享受类型检查了。
你还可以使用 Webpack 的另一个插件忽略掉 d.ts 文件,避免因为编译生成 d.ts 文件导致又重新检查。
new webpack.WatchIgnorePlugin([
/\.d\.ts$/,
]),
在 ts-loader 的仓库中,还有其他的一些提高编译速度的讨论,例如使用 cache-loader 或者 thread-loader,或者使用 happypack,但是这三个库我都试过了,并没有提升,一点提升都没有,反而降速了。也有尝试了 awesome-typescript-loader 但编译就直接失败了,想想 ts-loader 跟 ForkTsCheckerWebpackPlugin 一起工作也不慢,就暂时这样了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(23)
1、配置 externals,工具库直接使用 cdn,不需要打包,例如:vue,vue-router 等。
2、在处理 loader 时,配置 include,缩小 loader 检查范围。
3、使用 alias 可以更快地找到对应文件。
4、如果在 require 模块时不写后缀名,默认 webpack 会尝试.js,.json 等后缀名匹配,配置 extensions,可以让 webpack 少做一点后缀匹配。
5、thread-loader 可以将非常消耗资源的 loaders 转存到 worker pool 中。
6、使用 cache-loader 启用持久化缓存。使用 package.json 中的 postinstall 清除缓存目录。
使用webpack5,速度有质一般提升
参考
不写js
冷水
1.externals方案的缺点是什么呢,是外链的包如果升级需要手动添加hash
2.拆分dll,本身并没有问题,但是放在服务器部署的时候,那什么时候应该构建dll的部分是一个js界通用难题
我工作中用到优化:
npm run build --report
去观察各个文件的大小,使用externals方案及引入cdn, 或者按需加载(比如: element-ui)@dhbdn 使用externals 之后需要手动维护这些文件 升级需要添加手动添加hash 这个怎么破
这个可以自动化, html-webpack-tags-plugin 插件在生产环境时自动插入script标签
可以根据版本生成hash加在标签链接上
载入内置模块 载入文件模块 载入文件目录模块 载入node_modules里的模块 自动缓存已载入模块 如果模块名不是路径,也不是内置模块,Node将试图去当前目录的node_modules文件夹里搜索。如果当前目录的node_modules里没有找到,Node会从父目录的node_modules里搜索,这样递归下去直到根目录。
通用环境:
开发环境:

生产环境:

参考:https://webpack.docschina.org/guides/build-performance
缩小文件搜索范围
减少打包文件
缓存
多进程
由于 JavaScript 是单线程模型,要想发挥多核 CPU 的能力,只能通过多进程去实现,而无法通过多线程实现。所以 happypack 应该是让 webapck 开启新的子进程,子进程处理完成之后把结果汇总到主进程中。
1、因webpack提供的UglifyJS插件采用单线程压缩,速度很慢。所以将此插件替换为webpack-parallel-uglify-plugin插件,此插件可以并行运行UglifyJS插件,可有效减少构建时间。
2、由于运行在node.js之上的webpack是单线程模型,所以webpack做事只能一件一件去做。HappyPack可以让webpack在同一时间处理多个任务,把任务分解给多个子进程去并发执行,处理完之后将结果发给主进程
3、使用dll plugin => dynamic link library plugin,其中UglifyJS插件也可进行替换,详细请看第一条。
楼下老哥说的对,已经修改,感谢指正 @zhixinpeng
详情可以参考webpack官方文档
1.先设externals选项 把一些能直接走cdn的库拿出去如vue,vue-router的
2.拆分dll,把node_modules中的一部分拿出去先打包成一个静态的文件,在配置里引入dll的json配置,js文件拿去cdn,如 echarts下选用的模块
然后打包的都基本是自己的业务代码了。。
当然还可以自己再抽离组件 放到cdn去
1.开启gzip压缩,这个需要服务端配合,以Nginx为例
1)在config/index.js 里面设置 productionGzip:true;
2)安装稳定版本的compression-webpack-plugin,注意别着急安装,因为安装最新版本的容易报错;
3)在/build/webpack.base.config.js文件,找到module.exports的module中的rules,将图片类,音视频类,字体类加上limit选项,这样打包时可缩小静态资源体积
4)在Nginx服务端的配置中设置gzip:on gzip_static:on
2.对于引用的第三方库,可以通过CDN的方式,在index.html中引入,然后在build/webpack.base.config.js中,添加配置排除掉这些第三方引用:
//index.html
<body>
<div></div>
<!-- built files will be auto injected -->
<script src="https://cdn.bootcss.com/vue/2.6.6/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script>
<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
<script src="https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts.min.js"></script>
</body>
//webpack.base.config.js
let webpackConfig={
...
externals:{
'vue':'vue',
'vue-router':'vue-router',
'axios':'axios',
'echarts':'echarts'
}
...
}
"打包慢",是一个综合的因素,和vue关系不大。
1:确保下webpack,npm, node 及主要库版本要新,比如:4.x比3.x提升很多。
2:loader范围缩小到src项目文件!一些不必要的loader能关就关了吧
3:eslint代码校验其实是一个很费时间的一个步奏。
:可以把eslint的范围缩小到src,且只检查*.js 和 *.vue
:生产环境不开启lint,使用pre-commit或者husky在提交前校验
4:happypack多进程进行
如果上面优化后,时间还是不满意的话,就尝试下5,6吧。
5:动态链接库(DllPlugin),楼上已说。有点类似配置的externals。
补充一下:
缺点:将不能按需加载,会将配置的第三方库全部打包进去。
推荐:可以将使用率较高的包采用dll方案。
6:HardSourceWebpackPlugin会将模块编译后进行缓存,第一次之后速度会明显提升。
说说我的处理方式吧,纯经验之谈
1.使用
webpack-bundle-analyzer
对项目进行模块分析生成report,查看report后看看哪些模块体积过大,然后针对性优化,比如我项目中引用了常用的UI库element-ui和v-charts等2.配置webpack的
externals
,官方文档的解释:防止将某些import
的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖。所以,可以将体积大的库分离出来:
3.然后在
main.js
中移除相关库的import4.在
index.html
模板文件中,添加相关库的cdn
引用,如:经过以上的处理,再尝试编译打包,会发现速度快了一些。
有什么更好的方式或不对的地方欢迎指出
webpack 和 vue都不用
不用webpack
不用vue
happypack多线程插件,DllPlugin