Open yygmind opened 5 years ago
不用vue
不用webpack
webpack 和 vue都不用
说说我的处理方式吧,纯经验之谈
1.使用webpack-bundle-analyzer
对项目进行模块分析生成report,查看report后看看哪些模块体积过大,然后针对性优化,比如我项目中引用了常用的UI库element-ui和v-charts等
2.配置webpack的externals
,官方文档的解释:防止将某些import
的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖。
所以,可以将体积大的库分离出来:
// ...
externals: {
'element-ui': 'Element',
'v-charts': 'VCharts'
}
3.然后在main.js
中移除相关库的import
4.在index.html
模板文件中,添加相关库的cdn
引用,如:
<script src="https://unpkg.com/element-ui@2.10.0/lib/index.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/v-charts/lib/index.min.js"></script>
经过以上的处理,再尝试编译打包,会发现速度快了一些。 有什么更好的方式或不对的地方欢迎指出
"打包慢",是一个综合的因素,和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.开启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 id="app"></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'
}
...
}
1.先设externals选项 把一些能直接走cdn的库拿出去如vue,vue-router的 2.拆分dll,把node_modules中的一部分拿出去先打包成一个静态的文件,在配置里引入dll的json配置,js文件拿去cdn,如 echarts下选用的模块 然后打包的都基本是自己的业务代码了。。 当然还可以自己再抽离组件 放到cdn去
1. 使用最新版的webpack,官方会优化模块的解析速度
2.缩小loader的查询范围,例如:rules中loader添加:`include: path.resolve(__dirname, 'src')`
3. 用DllPlugin插件单独编译一些不经常改变的代码,比如node_modules的第三方库
4.删除不需要的一些代码,利用SplitChunksPlugin 进行分块
5.cache-loader来进行缓存持久化
6.不同的devtool配置也会影响性能,最好配置为‘eval’,或者‘cheap-module-eval-source-map’
1、因webpack提供的UglifyJS插件采用单线程压缩,速度很慢。所以将此插件替换为webpack-parallel-uglify-plugin插件,此插件可以并行运行UglifyJS插件,可有效减少构建时间。
//首先下载插件 npm i -D webpack-parallel-uglify-plugin
//修改 webpack.prod.conf.js
//将引入的UglifyJS 和 作用代码注释掉 并替换成下方代码
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
new ParallelUglifyPlugin({
cacheDir: '.cache/',
uglifyJS:{
output: {
comments: false
},
compress: {
warnings: false,
drop_debugger: true,
drop_console: false
}
}
}),
2、由于运行在node.js之上的webpack是单线程模型,所以webpack做事只能一件一件去做。HappyPack可以让webpack在同一时间处理多个任务,把任务分解给多个子进程去并发执行,处理完之后将结果发给主进程
//首先下载插件 npm install --save-dev happypack
//修改 webpack.base.conf.js
const HappyPack = require('happypack')
const os = require('os')
let happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
//加入此插件
plugins:[
new HappyPack({
id:'babel',
loaders:['babel-loader?cacheDirectory=true'],
threadPool:happyThreadPool
})
],
//将js loader作用代码替换
// loader: 'babel-loader' 替换成下方loader
loader: 'happypack/loader?id=babel',
3、使用dll plugin => dynamic link library plugin,其中UglifyJS插件也可进行替换,详细请看第一条。
//首先在build文件下创建一个js文件,webpack.dll.conf.js,并写入下方代码
const path = require("path")
const webpack = require("webpack")
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const pkg = require('../package')//引入package文件,目的就是找到依赖
module.exports = {
// 想要打包的模块的数组
entry: {
// vendor: ['axios', 'vue-router', 'vue','weixin-js-sdk','element-ui','vuex']
vendor:Object.keys(pkg.dependencies)//取出所有依赖单独打包
},
output: {
path: path.join(__dirname, '../static/js'), // 打包后文件输出的位置
filename: '[name].dll.js',//生成的文件名字 默认为vendor.dll.js
library: '[name]_library'//生成文件的映射关系,与下面的DLLPlugin配置相对应
},
plugins: [
new webpack.DllPlugin({//生成一个json文件 里面是关于dll.js的配置信息
path: path.join(__dirname, '.', '[name]-manifest.json'),
name: '[name]_library',//与上面output中的配置对应
context: __dirname//上下文环境路径,必须填写,为了与DLLReferencePlugin存在于同一上下文中,否则undefined
}),
// 压缩打包的文件
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
}),
]
}
//然后在webpack.prod.conf.js和webpack.dev.conf.js中加入当前插件
new webpack.DllReferencePlugin({
context: __dirname,//与DllPlugin中的context保持一致
/*这个地址对应webpack.dll.conf.js中生成的那个json文件的路径,这样webpack打包的时候
会检测当前文件中的映射,不会把已经存在映射的包再次打包进bundle.js */
manifest: require('./vendor-manifest.json')
}),
//在package.json中新加一条npm命令,执行webpack.dll.conf.js文件
"dll": "webpack --config ./build/webpack.dll.conf.js"
//tips:每次添加新依赖后,一定要运行npm run dll这个命令一次。
//最后在index.html中引入static/js/vendor.dll.js文件
<script src="static/js/vendor.dll.js"></script>
楼下老哥说的对,已经修改,感谢指正 @zhixinpeng
1、因webpack提供的UglifyJS插件采用单线程压缩,速度很慢。所以将此插件替换为webpack-parallel-uglify-plugin插件,此插件可以并行运行UglifyJS插件,可有效减少构建时间。
//首先下载插件 npm i -D webpack-parallel-uglify-plugin //修改 webpack.prod.conf.js //将引入的UglifyJS 和 作用代码注释掉 并替换成下方代码 const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin') new ParallelUglifyPlugin({ cacheDir: '.cache/', uglifyJS:{ output: { comments: false }, compress: { warnings: false, drop_debugger: true, drop_console: false } } }),
2、happypack,因nodejs是单线程执行编译,而happypack是启动node的多线程进行构建,进而提高构建速度
//首先下载插件 npm install --save-dev happypack //修改 webpack.base.conf.js const HappyPack = require('happypack') const os = require('os') let happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length }); //加入此插件 plugins:[ new HappyPack({ id:'babel', loaders:['babel-loader?cacheDirectory=true'], threadPool:happyThreadPool }) ], //将js loader作用代码替换 // loader: 'babel-loader' 替换成下方loader loader: 'happypack/loader?id=babel',
3、使用dll plugin => dynamic link library plugin,其中UglifyJS插件也可进行替换,详细请看第一条。
//首先在build文件下创建一个js文件,webpack.dll.conf.js,并写入下方代码 const path = require("path") const webpack = require("webpack") const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const pkg = require('../package')//引入package文件,目的就是找到依赖 module.exports = { // 想要打包的模块的数组 entry: { // vendor: ['axios', 'vue-router', 'vue','weixin-js-sdk','element-ui','vuex'] vendor:Object.keys(pkg.dependencies)//取出所有依赖单独打包 }, output: { path: path.join(__dirname, '../static/js'), // 打包后文件输出的位置 filename: '[name].dll.js',//生成的文件名字 默认为vendor.dll.js library: '[name]_library'//生成文件的映射关系,与下面的DLLPlugin配置相对应 }, plugins: [ new webpack.DllPlugin({//生成一个json文件 里面是关于dll.js的配置信息 path: path.join(__dirname, '.', '[name]-manifest.json'), name: '[name]_library',//与上面output中的配置对应 context: __dirname//上下文环境路径,必须填写,为了与DLLReferencePlugin存在于同一上下文中,否则undefined }), // 压缩打包的文件 new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false } }, }), ] } //然后在webpack.prod.conf.js和webpack.dev.conf.js中加入当前插件 new webpack.DllReferencePlugin({ context: __dirname,//与DllPlugin中的context保持一致 /*这个地址对应webpack.dll.conf.js中生成的那个json文件的路径,这样webpack打包的时候 会检测当前文件中的映射,不会把已经存在映射的包再次打包进bundle.js */ manifest: require('./vendor-manifest.json') }), //在package.json中新加一条npm命令,执行webpack.dll.conf.js文件 "dll": "webpack --config ./build/webpack.dll.conf.js" //tips:每次添加新依赖后,一定要运行npm run dll这个命令一次。 //最后在index.html中引入static/js/vendor.dll.js文件 <script src="static/js/vendor.dll.js"></script>
由于 JavaScript 是单线程模型,要想发挥多核 CPU 的能力,只能通过多进程去实现,而无法通过多线程实现。所以 happypack 应该是让 webapck 开启新的子进程,子进程处理完成之后把结果汇总到主进程中。
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)我工作中用到优化:
- 排除不用的第三方包,
- 使用
npm run build --report
去观察各个文件的大小,使用externals方案及引入cdn, 或者按需加载(比如: element-ui)- 处理 loader 时,配置 include,exclude,缩小 loader 检查范围
- webpack-parallel-uglify-plugin插件, 减少的构建时间
- eslint不检测或者缩小检测范围
- 使用gzip压缩
@dhbdn 使用externals 之后需要手动维护这些文件 升级需要添加手动添加hash 这个怎么破
我工作中用到优化:
- 排除不用的第三方包,
- 使用
npm run build --report
去观察各个文件的大小,使用externals方案及引入cdn, 或者按需加载(比如: element-ui)- 处理 loader 时,配置 include,exclude,缩小 loader 检查范围
- webpack-parallel-uglify-plugin插件, 减少的构建时间
- eslint不检测或者缩小检测范围
- 使用gzip压缩
@dhbdn 使用externals 之后需要手动维护这些文件 升级需要添加手动添加hash 这个怎么破
这个可以自动化, html-webpack-tags-plugin 插件在生产环境时自动插入script标签 可以根据版本生成hash加在标签链接上
// 自动externals配置, 打包阶段走cdn
if (process.env.NODE_ENV === 'production') {
const [webpackExternals, scripts] = formatExternal(externals)
debug(`use externals ${JSON.stringify(webpackExternals)}`)
scripts.forEach((url) => debug(`external link: ${url}`))
chain.externals(webpackExternals)
chain.plugin('InjectExternalsToHtml').use(HtmlWebpackTagsPlugin, [{ append: false, usePublicPath: false, scripts }])
}
缩小文件搜索范围
减少打包文件
缓存
多进程
缩小loader的查找范围 提取公共库 ,减少参与不必要的打包体积 开启缓存,加快构建速度 开启多进程,并发处理,加快loader处理速度
happypack多线程插件,DllPlugin