从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 相关文章推荐
Tab页界面 用jQuery及Ajax技术实现(php后台)
Oct 12 Javascript
JS获取html对象的几种方式介绍
Dec 05 Javascript
js正则表达式中test,exec,match方法的区别说明
Jan 29 Javascript
查找Oracle高消耗语句的方法
Mar 22 Javascript
JS判断、校验MAC地址的2个实例
May 05 Javascript
js实现简单随机抽奖的方法
Jan 27 Javascript
js实现的星星评分功能函数
Dec 09 Javascript
AngularJs Modules详解及示例代码
Sep 01 Javascript
Bootstrap 模态框(Modal)插件代码解析
Dec 21 Javascript
jquery点赞功能实现代码 点个赞吧!
May 29 jQuery
JavaScript闭包和回调详解
Aug 09 Javascript
一文了解JavaScript用Element Traversal新属性遍历子元素
Nov 27 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文本操作类
2006/11/25 PHP
让PHP支持页面回退的两种方法[转]
2007/02/14 PHP
详解PHP中strlen和mb_strlen函数的区别
2014/03/07 PHP
简单的php新闻发布系统教程
2014/05/09 PHP
Yii2中OAuth扩展及QQ互联登录实现方法
2016/05/16 PHP
不能再简单的无闪刷新验证码原理很简单
2007/11/05 Javascript
JavaScript 学习点滴记录
2009/04/24 Javascript
js 上传图片预览问题
2010/12/06 Javascript
学习从实践开始之jQuery插件开发 菜单插件开发
2012/05/03 Javascript
JS图片预加载 JS实现图片预加载应用
2012/12/03 Javascript
IE不支持getElementsByClassName最终完美解决方案
2012/12/17 Javascript
JS文本框默认值处理详解
2013/07/10 Javascript
js中Image对象以及对其预加载处理示例
2013/11/20 Javascript
HTML页面登录时的JS验证方法
2014/05/28 Javascript
javascript获取checkbox复选框获取选中的选项
2014/08/12 Javascript
JavaScript 经典实例日常收集整理(常用经典)
2016/03/30 Javascript
正则表达式(语法篇推荐)
2016/06/24 Javascript
js滚轮事件兼容性问题需要注意哪些
2016/11/15 Javascript
完美解决jQuery的hover事件在IE中不停闪动的问题
2017/02/10 Javascript
浅谈js中用$(#ID)来作为选择器的问题(id重复的时候)
2017/02/14 Javascript
使用gulp搭建本地服务器并实现模拟ajax
2017/04/05 Javascript
ES6新特性:使用export和import实现模块化详解
2017/07/31 Javascript
vue-cli之router基本使用方法详解
2017/10/17 Javascript
[02:47]DOTA2亚洲邀请赛 HR战队出场宣传片
2015/02/07 DOTA
Python获取系统默认字符编码的方法
2015/06/04 Python
python字符串分割及字符串的一些常规方法
2019/07/24 Python
一款利用纯css3实现的win8加载动画的实例分析
2014/12/11 HTML / CSS
canvas 基础之图像处理的使用
2020/04/10 HTML / CSS
美国创意礼品网站:UncommonGoods
2017/02/03 全球购物
ASOS英国官网:英国在线时装和化妆品零售商
2017/05/19 全球购物
PHP如何去执行一个SQL语句
2016/03/05 面试题
ruby如何进行集成操作?Ruby能进行多重继承吗?
2013/10/16 面试题
旷课检讨书3000字
2014/02/04 职场文书
中国梦口号
2014/06/13 职场文书
员工辞退通知书
2015/04/17 职场文书
python pygame入门教程
2021/06/01 Python