vue webpack打包优化操作技巧


Posted in Javascript onFebruary 22, 2018

临近春节,公司很多同事都提前回家过年,剩余人员根据禅道去修改bug,当bug修正完毕以后,我们需要重新打包给运维,上测试服给测试同事提测,但是由于项目本体比较庞大,所以打包时间太过漫长(二十五分钟以上:sob:),所以有了打包优化的想法(其实想法早就有了,但是因为平时工作计划比较充实,所以一直没有去完成这个工作),这次正好有时间,所以去重新考虑了这个问题!

webpack是react项目标配的打包工具,和NPM搭配起来使用管理模块实在非常方便。

  webapck 把所有的静态资源都看做是一个 module,通过 webpack,将这些 module 组成到一个 bundle 中去,从而实现在页面上引入一个 bundle.js,来实现所有静态资源的加载。

话不多说,直接开始正文吧

先给大家看一下项目的目录结构:

vue webpack打包优化操作技巧 

就是正常的项目结构,简单说一下吧:

  • build文件夹包含的是一些打包配置的一下东西
  • config文件夹是项目的基础配置
  • dist是打包之后的文件
  • node_modules是项目的依赖包
  • src文件夹里面是项目的源码
  • static文件夹里面放的是一些项目使用的静态资源
  • index.html是项目的首页
  • package.json文件是项目的配置json
  • yarn.lock是使用yarn锁定项目用的依赖

优化思路

项目打包时间长,原因无外乎就是项目整体比较庞大、依赖复杂、组件之前拆分不够合理。

对于这三个问题呢,我们可以针对下面这几个方面去做一下处理:

  • 对项目进行路由屏蔽,只打包自己需要打包的部分(我司就是好几个项目合并在了一起,至于原因则是 需求类似,所以放在一起比较省事 -_-||| 开发过程中是省了不少事,但是现在一样要还的!!!!)
  • 依赖关系复杂,这里说的是项目中的依赖模块比较多,像我们现在这个项目,光算依赖包的话就有40+,另外一个重要原因就是组件之间存在相同引用的依赖。解决思路是把项目中重用的依赖抽离出来进行单独打包。
  • 组件在写的过程中,需要考虑好这个组件的使用方向,以及实现功能,不能混为一谈。

实际操作

有了整体的思路,那么开搞就可以啦 去webpack文档去看了一下有一个DllPlugin,这个插件就是帮助我们解决问题的关键,下面是我webpack.dll.config的代码:

var path = require("path");
var webpack = require("webpack");
function resolve (dir) {
 return path.join(__dirname, '..', dir)
}
module.exports = {
 // 你想要打包的模块的数组
 entry: {
 vendor: ['vue', 'lodash', 'vuex', 'axios', 'vue-router', 'iview', 'element-ui',
  'echarts','xlsx','jquery','vue-fullcalendar','vue-cookie','handsontable']
 },
 output: {
 path: path.join(__dirname, '../dist/vendor-dll-js'), // 打包后文件输出的位置
 filename: '[name].dll.js',
 library: '[name]_library'
 // vendor.dll.js中暴露出的全局变量名。
 // 主要是给DllPlugin中的name使用,
 // 故这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
 },
 resolve: {
 extensions: ['.js', '.vue', '.json'],
 alias: {
  'vue$': 'vue/dist/vue.esm.js',
  '@': resolve('src'),
 }
 },
 plugins: [
 new webpack.DllPlugin({
  path: path.join(__dirname, '.', '[name]-manifest.json'),
  name: '[name]_library',
  context: __dirname
 }),
 // 压缩打包的文件,与该文章主线无关
 new webpack.optimize.UglifyJsPlugin({
  compress: {
  warnings: false
  }
 })
 ]
};

我们需要将项目中具有重用性的包抽离出来,放在vendor数组里面,然后在下面output里面定义一下打包输出的文件路径,然后在resolve里面配置解析参数,最后定义使用的DllPlugin插件,UglifyJsPlugin是压缩js的插件

Dllplugin里的path,会输出一个vendor-manifest.json,这是用来做关联id的,打包的时候不会打包进去,所以不用放到static里 然后运行一下 webpack -p --progress --config build/webpack.dll.conf.js

成功以后,static下会有dll.vendor.js,根目录下会有vendor.manifest.json 各自打开看一下,就会看到依赖库的源码和匹配id

ok,到这里,抽离依赖库的事情就完成了,那么接下来问题就是怎么引用呢,怎么在dev和build跑呢?

这里补了一点dll和commonsChunk概念上的区别,commonsChunk之所以慢和大,是因为每次run的时候,都会去做一次打包,而实际上我们不会一直去更新我们引用的依赖库,所以dll的做法就等于是,事先先打包好依赖库,然后只对每次都修改的js做打包。

继续上面的步骤,我们需要根据生成的json文件去修改webpack.base.config文件:

const manifest = require('../vendor-manifest.json')
......
plugins: [
 new webpack.DllReferencePlugin({
  manifest
 })
 ]

然后打开index.html,在底部加上 <script src="./static/dll.vendor.js"></script>

执行一下 npm run build ,一起正常的话,表示你的操作是正确的。

升级处理

至此优化的问题基本已经解决了,但是在处理过程中需要进行复制粘贴,还要对index.html文件进行操作,如果是对于项目不熟悉的人来进行开发项目的话,就会出现一些小的问题,所以我决定继续往下研究一下:

思路还是上面的思路,我们下面需要进行的操作呢就是对与之前的处理进行优化,通过配置文件,和命令去实现我们想要的效果

首先我们将上面 webpack.dll.config 文件里面的entry配置项拿出来,在config文件夹下新建一个dll.js

module.exports = {
 entry: {
 // 这里的依赖顺序必须是:对象从上往下依赖,数组从右到左依赖(如果互不依赖的可以忽略顺序)
 ui: ['iview', 'element-ui'],
 tool: ['lodash', 'jquery', 'axios', 'vue-fullcalendar'],
 vue: ['vue', 'vuex', 'vue-router', 'vue-cookie'],
 xlsx: ['xlsx'],
 echarts: ['echarts'],
 other: ['handsontable'],
 },
 outFile: '../static/dll'
};

这里面其实就是我们一开始写的entry的配置项,根据这个js去打包的文件有一个顺序,就是我总结的这个:

这里的依赖顺序必须是:对象从上往下依赖,数组从右到左依赖(如果互不依赖的可以忽略顺序)

如果不按照这个顺序去写的话,会出现依赖错误的问题!!!

然后在output里面再进行一下配置:

output: {
 path: path.join(__dirname, dllConfig.outFile), // 打包后文件输出的位置
 filename: '[name].dll.[chunkhash].js',
 library: '[name]_library'
 // 主要是给DllPlugin中的name使用,
 // 故这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
 },

这样在执行 webpack -p --progress --config build/webpack.dll.conf.js 指令的时候会生成如下:

vue webpack打包优化操作技巧 

是不是看到文件后面的hash就一脸懵逼,这怎么办,我们没有办法去进行复制粘贴了!!(我们的目的不就是不进行复制粘贴吗 正经脸-_-)

要实现命令操作之后不进行复制粘贴操作就需要使用webpack的HtmlWebpackPlugin插件

在plugins里面配置一下HtmlWebpackPlugin

new HtmlWebpackPlugin({
 filename: path.join(__dirname, '../', config.dev.index),
 template: 'index.ejs',
 inject: false
}),

然后在根目录添加一个index.ejs模版(ejsGitHub地址 ), index.ejs中代码如下:

<body>
 <div id="app"></div>
 <!-- dll files will be auto injected -->
 <% for (var chunk in htmlWebpackPlugin.files.chunks) { %><script type="text/javascript" src="/<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
 <% } %>
 <!-- built files will be auto injected -->
</body>

最后需要在config文件夹下的index.js进行一下修改: 在dev中添加: index: 'index.html',

项目在执行dev指令或者build指令之前需要先执行: webpack -p --progress --config build/webpack.dll.conf.js 在dll指令结束后 执行其他操作就可以完美的玩耍了:blush:

总结

至此代码打包优化的整个过程就基本结束了,测试一下,15分钟左右就可以完成打包,比之前打包快了将近10分钟,可以说是非常成功的一次尝试!!

Javascript 相关文章推荐
javascript开发技术大全 第4章 直接量与字符集
Jul 03 Javascript
优化Jquery,提升网页加载速度
Nov 14 Javascript
javascript实现点击按钮让DIV层弹性移动的方法
Feb 24 Javascript
对jQuary选择器的全面总结
Jun 20 Javascript
项目实践一图片上传之form表单还是base64前端图片压缩(前端图片压缩)
Jul 28 Javascript
从0开始学Vue
Oct 27 Javascript
webpack 2.x配置reactjs基本开发环境详解
Aug 08 Javascript
详解angularJS+Ionic移动端图片上传的解决办法
Sep 13 Javascript
ionic选择多张图片上传的示例代码
Oct 10 Javascript
微信小程序如何实现精确的日期时间选择器
Jan 21 Javascript
浅谈实现在线预览PDF的几种解决办法
Aug 10 Javascript
vue实现点击按钮“查看详情”弹窗展示详情列表操作
Sep 09 Javascript
vue和react等项目中更简单的实现展开收起更多等效果示例
Feb 22 #Javascript
Vue 2.5.2下axios + express 本地请求404的解决方法
Feb 21 #Javascript
把vue-router和express项目部署到服务器的方法
Feb 21 #Javascript
浅谈在vue中用webpack打包之后运行文件的问题以及相关配置方法
Feb 21 #Javascript
浅谈webpack打包过程中因为图片的路径导致的问题
Feb 21 #Javascript
解决vue打包之后静态资源图片失效的问题
Feb 21 #Javascript
Vue项目中设置背景图片方法
Feb 21 #Javascript
You might like
百度工程师讲PHP函数的实现原理及性能分析(三)
2015/05/13 PHP
php实现将HTML页面转换成word并且保存的方法
2016/10/14 PHP
jquery ajax 同步异步的执行示例代码
2010/06/23 Javascript
javascript alert乱码的解决方法
2013/11/05 Javascript
NodeJS学习笔记之MongoDB模块
2015/01/13 NodeJs
jQuery Html控件基本操作(日常收集整理)
2016/03/11 Javascript
jquery实现左右无缝轮播图
2020/07/31 Javascript
angularjs封装bootstrap时间插件datetimepicker
2016/06/20 Javascript
js 模仿锚点定位的实现方法
2016/11/19 Javascript
前端面试知识点锦集(JavaScript篇)
2016/12/28 Javascript
js遍历json的key和value的实例
2017/01/22 Javascript
简单理解Vue中的nextTick方法
2018/01/30 Javascript
vue分页器组件编写方法详解
2019/06/28 Javascript
使用React-Router实现前端路由鉴权的示例代码
2020/07/26 Javascript
javascript实现打砖块小游戏(附完整源码)
2020/09/18 Javascript
[36:33]Ti4 循环赛第四日 附加赛NEWBEE vs Mouz
2014/07/13 DOTA
Python扫描IP段查看指定端口是否开放的方法
2015/06/09 Python
一个基于flask的web应用诞生 使用模板引擎和表单插件(2)
2017/04/11 Python
Python利用Django如何写restful api接口详解
2018/06/08 Python
Sanic框架应用部署方法详解
2018/07/18 Python
Django-xadmin+rule对象级权限的实现方式
2020/03/30 Python
Pytorch十九种损失函数的使用详解
2020/04/29 Python
Python网络爬虫四大选择器用法原理总结
2020/06/01 Python
Python实现AES加密,解密的两种方法
2020/10/03 Python
维珍澳洲航空官网:Virgin Australia
2017/09/08 全球购物
中学教师实习自我鉴定
2013/09/28 职场文书
应届毕业生求职信范文
2014/07/07 职场文书
离婚协议书范本(通用篇)
2014/11/30 职场文书
2015年学校教研室主任工作总结
2015/07/20 职场文书
2016年大学生就业指导课心得体会
2015/10/09 职场文书
2016年暑假学生家长评语
2015/12/01 职场文书
初中数学课堂教学反思
2016/02/17 职场文书
Python 流媒体播放器的实现(基于VLC)
2021/04/28 Python
教你做个可爱的css滑动导航条
2021/06/15 HTML / CSS
SpringCloud Alibaba项目实战之nacos-server服务搭建过程
2021/06/21 Java/Android
MySQL学习之基础命令实操总结
2022/03/19 MySQL