从0到1搭建element后台框架优化篇(打包优化)


Posted in Javascript onMay 12, 2019

前言

hello,咱又见了~~嘻嘻。本次主要来说说这个打包优化的问题。一个vue项目从开发到上线必须得经历打包过程,一个项目的打包优化与否都决定了你这个项目的运行速度以及用户体验。本次主要是针对vue.config,js的配置进行优化。项目地址

开发环境与生产环境

开发环境与生产环境的配置也是开发中的必不可少的一环。本项目是由vue-cli3开发,vue-cli3深度集成了webpack,如果不熟悉vue-cli3可以先去官网看看相关配置。

开发环境

在项目根目录下新建.env.development文件表明是开发环境。

VUE_APP_CURRENTMODE ="development" //当前的环境
 VUE_APP_LOGOUT_URL="http://localhost:3000/" //开发环境的地址

生产环境

在项目根目录下新建.env.production文件表明是生产环境。

VUE_APP_CURRENTMODE ="development" //当前的环境
 VUE_APP_LOGOUT_URL="xxx" //生产环境的地址

当然你也可以自己创建一个测试环境.env.test,同样可以像上边一样配置。

环境运用

那么接下来我们怎么用它呢?这里不得不说一下的是package.json里面的两个命令serve,build,其实对应的是全命令是vue-cli-service serve --mode development,vue-cli-service build --mode production,如果你想要在构建命令中使用开发环境变量,那么可以加入

"dev-build": "vue-cli-service build --mode development"

接下来在vue.config.js运用它。

config.plugin('define').tap(args => {
   args[0]['process.env'].VUE_APP_LOGOUT_URL = JSON.stringify(process.env.VUE_APP_LOGOUT_URL)
   console.log(args[0])
   return args;
 });

这里有必要说下,这段代码是写在chainWebpack配置项下面。这段代码其实运用了两个webpack插件webpack-chain允许配置链式操作,以及webpack.DefinePlugin。

  1. webpack-chain:尝试通过提供可链式或顺流式的 API 创建和修改webpack 配置。了解更多
  2. webpack.DefinePlugin:它的作用是定义全局常量,是常量。即在模块用它定义的全局常量,那么你就不能改变它。也就是说我定义了一个process.env.VUE_APP_LOGOUT_URL常量,在src文件夹下面都可以使用。了解更多

分包(code splitting)

首先思考,我们引入的第三方包与我们的业务代码一起打包会产生什么问题?

顾名思义,我们的业务代码变动比较频繁,而我们引入的第三方包基本上不会变动。浏览器会有缓存,没有变动的文件会直接从缓存中读取,这也间接的优化了网站的访问速速。

接下来配置vue.config.js,

分割第三方库

//代码分割
 config.optimization.minimize(true);
 config.optimization.splitChunks({
  chunks: 'all',
  cacheGroup:{
  //vue2-editor单独打一个包
   vueEdior: {
   name: 'vueEdior',
   test: /[\\/]node_modules[\\/]vue2-editor[\\/]/,
   priority: 10 // 优先级要大于 vendors 不然会被打包进 vendors
   },
   //其余的第三方包打进vendor
   vendors: {
   test: /[\\/]node_modules[\\/]/,
   priority: -10
   }
  }
 })

分割共用文件

组件是vue项目的重要组成部分。相当一部分组件都可以公用,在不同的文件中引入,因此我们可以将这部分公用的组件直接分割出来。

config.optimization.minimize(true);
 config.optimization.splitChunks({
  chunks: 'all',
  cacheGroup:{
   vueEdior: {
   name: 'vueEdior',
   test: /[\\/]node_modules[\\/]vue2-editor[\\/]/,
   priority: 10 // 优先级要大于 vendors 不然会被打包进 vendors
   },
   public: {
   name: 'public',
   test: resolve('src/components'),
   minSize: 0, //表示在压缩前的最小模块大小,默认值是 30kb
   minChunks: 2, // 最小公用次数
   priority: 5, // 优先级
   reuseExistingChunk: true // 公共模块必开启
   },
   //其余的第三方包打进vendor
   vendors: {
   test: /[\\/]node_modules[\\/]/,
   priority: -10
   }
  }
 })

打包完后会发现dist/static/js,多了一个vueEditor和public文件,这就表明分割完成。

map文件处理和别名设置(alias)

map文件

我们可以进一步优化,打包默认生成map文件,从而导致包的体积过大,这时我们需要设定一个属性来关闭它。

productionSourceMap: false

别名设置

alias运用的好处在于不用一级级的去找,而是直接锁定位置,从而减少文件搜索时间。

//设置别名
 config.resolve.alias
  .set('@', resolve('src'))
  .set('@api', resolve('src/api/api'))//接口地址
  .set('@assets', resolve('src/assets'))

gzip压缩与去console插件

如果上面的方式都编写了,文件依旧过大,这个时候不得不考虑代码压缩和去掉console插件了,可以说为了优化项目,“无所不用其极”。

gzip压缩

首先安装开始安装

cnpm install compression-webpack-plugin --save-dev

然后在configureWebpack里面配置它

const CompressionWebpackPlugin = require('compression-webpack-plugin')
 new CompressionWebpackPlugin({
  filename: '[path].gz[query]',
  algorithm: 'gzip',
  test: new RegExp(
   '\\.(' +
   ['js', 'css'].join('|') +
   ')$',
  ),
  threshold: 10240,
  minRatio: 0.8,
  }),

值得注意的是gzip压缩文件需要后端来配合支持,如果后端没有支持那么项目加载的依旧是没有压缩的文件。

去console插件

首先安装

cnpm install uglifyjs-webpack-plugin --save-dev

然后在configureWebpack里面配置它

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
 new UglifyJsPlugin({
  uglifyOptions: {
   compress: {
   warnings: false,
   drop_debugger: true,
   drop_console: true,
   },
  },
  sourceMap: false,
  parallel: true,
  }),

cdn引入

有的同学说后端没有支持gzip压缩加载,那怎么办?那只有凉拌咯~~~。
这里给大家介绍一个cdn引入的方式,有的第三方插件太大,导致单独分包后还是挺大的,这个时候可以考虑用cdn的方式引入文件。

无插件引入cdn

首先我们不让webpack打包用cdn引入的文件

   

//对一些不经常改动的库,可以通过cdn引入,webpack不对他们打包 
 let externals = {
  'vue': 'Vue',
  'axios': 'axios',
  'element-ui': 'ELEMENT',
  'vue-router': 'VueRouter',
  'vuex': 'Vuex',
  'echarts': 'echarts',
  'vue2-editor': 'VueEditor'
 }

然后配置cdn

 

const cdn = {
  css: [
  //element-ui css
  'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
  ],
  js: [
  //vue
  'https://unpkg.com/vue@2.6.10/dist/vue.min.js',
  //axios
  'http://cdn.staticfile.org/axios/0.19.0-beta.1/axios.min.js',
  //vuex
  'https://unpkg.com/vuex@3.1.0/dist/vuex.min.js',
  //vue-router
  'https://unpkg.com/vue-router@3.0.6/dist/vue-router.min.js',
  //element
  'https://unpkg.com/element-ui@2.7.2/lib/index.js',
  //echarts
  'https://cdn.jsdelivr.net/npm/echarts@4.2.1/dist/echarts.min.js',
  //vue2-editor
  "https://unpkg.com/vue2-editor@2.6.6/dist/vue2-editor.js"
  ]
 }

接下来在chainWebpack配置

process.env.VUE_APP_CURRENTMODE === 'production') {
  config.externals(externals)//忽略打包
  config.plugin('html')
  .tap(args => {
   args[0].cdn = cdn;
   return args
  })
 }

这里需要解释的是config.plugin('html')其实是运用了 html-webpack-plugin插件在其实例化的options挂载cdn对象,然后通过ejs模板语法,读取相关cdn。

紧接着我们需要在public/index.html中读取相关cdn

<% if (process.env.VUE_APP_CURRENTMODE === 'production') { %>
  <% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
  <link rel="stylesheet" href="<%=css%>" rel="external nofollow" as="style">
  <% } %>
  <% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
  <script src="<%=js%>"></script>
  <% } %>
 <% } %>

至此cdn引入完成

插件引入cdn

由于手动引入cdn太过麻烦,而且担心版本变化,每次都需要手动去更改,所以为了更好的开发体验,引入了自动匹配cdn插件,webpack-cdn-plugin。接下来开始安装

cnpm install webpack-cdn-plugin --save

实例化插件

const cdnPlugin = require('webpack-cdn-plugin')

接下来开始在configureWebpack中引用

new cdnPlugin({
  modules: [
   { name: 'vue', var: 'Vue', path: 'dist/vue.min.js' },
   { name: 'axios', var: 'axios', path: 'dist/axios.min.js' },
   { name: 'vuex', var: 'Vuex', path: 'dist/vuex.min.js' },
   { name: 'element-ui', var: 'ELEMENT', path: 'lib/index.js', style: 'lib/theme-chalk/index.css' },
   { name: 'echarts', var: 'echarts', path: 'dist/echarts.min.js' },
   { name: 'vue2-editor', var: 'VueEditor', path: 'dist/vue2-editor.js' },
   { name: 'vue-router', var: 'VueRouter', path: 'dist/vue-router.min.js' },
  ],
  publicPath: '/node_modules'
  })
  • name:插件名
  • var :项目中实例化的名字
  • path:路径名称
  • style:css路径名称

更多了解请参考官方文档。

总体来说引入第三方cdn确实能带来不错的效果,但是有可能不稳定,因此建议大家在实际开发中自己去申请一个专属的cdn域名,将网站所要用到库直接上传上去。

结语

本期的打包优化就到这里啦!感觉有很多废话。哈哈~~,最后感谢大家阅读,如果有问题以及错误请及时指正。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
一个JQuery写的点击上下滚动的小例子
Aug 27 Javascript
javascript简单实现表格行间隔显示颜色并高亮显示
Nov 29 Javascript
JS对象转换为Jquery对象实现代码
Dec 29 Javascript
javascript学习笔记(二)数组和对象部分
Sep 30 Javascript
使用纯javascript实现放大镜效果
Mar 18 Javascript
js+ajax实现获取文件大小的方法
Dec 08 Javascript
BooStrap对导航条的改造实践小结
Sep 21 Javascript
Vue实现virtual-dom的原理简析
Jul 10 Javascript
JS阻止事件冒泡的方法详解
Aug 26 Javascript
js脚本中执行java后台代码方法解析
Oct 11 Javascript
解决vue admin element noCache设置无效的问题
Nov 12 Javascript
Ant Design Vue 添加区分中英文的长度校验功能
Jan 21 Javascript
Vue项目服务器部署之子目录部署方法
May 12 #Javascript
vue配置接口域名方法总结
May 12 #Javascript
详解babel升级到7.X采坑总结
May 12 #Javascript
babel7.x和webpack4.x配置vue项目的方法步骤
May 12 #Javascript
vue轻量级框架无法获取到vue对象解决方法
May 12 #Javascript
使vue实现jQuery调用的两种方法
May 12 #jQuery
React优化子组件render的使用
May 12 #Javascript
You might like
php设计模式 Strategy(策略模式)
2011/06/26 PHP
php中{}大括号是什么意思
2013/12/01 PHP
Laravel中encrypt和decrypt的实现方法
2017/09/24 PHP
JavaScript 基于原型的对象(创建、调用)
2009/10/16 Javascript
js跑步算法的实现代码
2013/12/04 Javascript
javascript中JSON.parse()与eval()解析json的区别
2016/05/19 Javascript
angularjs实现下拉列表的选中事件示例
2017/03/03 Javascript
详解AngularJS跨页面传值(ui-router)
2017/08/23 Javascript
微信小程序 flexbox layout快速实现基本布局的解决方案
2020/03/24 Javascript
vue实现购物车加减
2020/05/30 Javascript
Python设计足球联赛赛程表程序的思路与简单实现示例
2016/06/28 Python
Python 模拟购物车的实例讲解
2017/09/11 Python
Python中数组,列表:冒号的灵活用法介绍(np数组,列表倒序)
2018/04/18 Python
浅析python参数的知识点
2018/12/10 Python
Python 运行 shell 获取输出结果的实例
2019/01/07 Python
python ChainMap 合并字典的实现步骤
2019/06/11 Python
详解Python利用random生成一个列表内的随机数
2019/08/21 Python
详解一种用django_cache实现分布式锁的方式
2019/09/01 Python
python批量修改交换机密码的示例
2020/09/22 Python
Python安装并操作redis实现流程详解
2020/10/13 Python
python使用selenium爬虫知乎的方法示例
2020/10/28 Python
经济系大学生求职信
2013/10/01 职场文书
求职自荐书范文
2013/12/04 职场文书
社区十八大感言
2014/01/19 职场文书
总经理岗位职责描述
2014/02/08 职场文书
《一个中国孩子的呼声》教学反思
2014/02/12 职场文书
建筑工地标语
2014/06/18 职场文书
个性车贴标语
2014/06/24 职场文书
通知格式
2015/04/27 职场文书
闪闪的红星观后感
2015/06/08 职场文书
舞出我人生观后感
2015/06/16 职场文书
简短清晨问候语
2015/11/10 职场文书
行政后勤人员工作计划应该怎么写?
2019/08/16 职场文书
SQL Server基本使用和简单的CRUD操作
2021/04/05 SQL Server
Mysql 性能监控及调优
2021/04/06 MySQL
Python的这些库,你知道多少?
2021/06/09 Python