从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实现的一个图片延迟加载插件(含图片延迟加载原理)
Jun 05 Javascript
简介AngularJS的HTML DOM支持情况
Jun 17 Javascript
理解javascript中的with关键字
Feb 15 Javascript
jQuery实现百叶窗焦点图动画效果代码分享(附源码下载)
Mar 14 Javascript
js中字符串编码函数escape()、encodeURI()、encodeURIComponent()区别详解
Apr 01 Javascript
详解JavaScript中双等号引起的隐性类型转换
May 30 Javascript
JS类的定义与使用方法深入探索
Nov 26 Javascript
js 实现省市区三级联动菜单效果
Feb 20 Javascript
关于预加载InstantClick的问题解决方法
Sep 12 Javascript
Bootstrap框架建立树形菜单(Tree)的实例代码
Oct 30 Javascript
vue脚手架搭建项目的兼容性配置详解
Jul 17 Javascript
JS闭包原理与应用经典示例
Dec 20 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
解析CI的AJAX分页 另类实现方法
2013/06/27 PHP
PHP性能分析工具xhprof的安装使用与注意事项
2017/12/19 PHP
php实现银联商务公众号+服务窗支付的示例代码
2019/10/12 PHP
JS获取图片实际宽高及根据图片大小进行自适应
2013/08/11 Javascript
JS选项卡动态替换banner图片路径的方法
2015/05/11 Javascript
详解AngularJS中的表达式使用
2015/06/16 Javascript
Javascript表单特效之十大常用原理性样例代码大总结
2016/07/12 Javascript
Vue.js学习笔记之 helloworld
2016/08/14 Javascript
Bootstrap Table表格一直加载(load)不了数据的快速解决方法
2016/09/17 Javascript
bootstrap jquery dataTable 异步ajax刷新表格数据的实现方法
2017/02/10 Javascript
微信小程序调用PHP后台接口 解析纯html文本
2017/06/13 Javascript
jQuery Validate格式验证功能实例代码(包括重名验证)
2017/07/18 jQuery
AngularJS 教程及实例代码
2017/10/23 Javascript
vue中SPA单页面应用程序详解
2017/11/07 Javascript
vue-cli3 从搭建到优化的详细步骤
2019/01/20 Javascript
layui动态绑定事件的方法
2019/09/20 Javascript
JS实现百度搜索框关键字推荐
2020/02/17 Javascript
ES2020 已定稿,真实场景案例分析
2020/05/25 Javascript
js 实现碰撞检测的示例
2020/10/28 Javascript
Angular处理未可知异常错误的方法详解
2021/01/17 Javascript
python实现决策树、随机森林的简单原理
2018/03/26 Python
opencv导入头文件时报错#include的解决方法
2019/07/31 Python
Python 获取指定文件夹下的目录和文件的实现
2019/08/30 Python
Python面向对象之Web静态服务器
2019/09/03 Python
python基于TCP实现的文件下载器功能案例
2019/12/10 Python
如何使用repr调试python程序
2020/02/28 Python
PyQt中使用QtSql连接MySql数据库的方法
2020/07/28 Python
美国专业汽车音响和移动电子产品零售商:Car Toys
2019/05/13 全球购物
学校联谊活动方案
2014/02/15 职场文书
《台湾的蝴蝶谷》教学反思
2014/02/20 职场文书
吃空饷专项整治方案
2014/10/27 职场文书
求职简历自我评价范文
2015/03/10 职场文书
小学六一儿童节活动总结
2015/05/05 职场文书
企业培训简报范文
2015/07/20 职场文书
Element-ui Layout布局(Row和Col组件)的实现
2021/12/06 Vue.js
ssh服务器拒绝了密码 请再试一次已解决(亲测有效)
2022/08/14 Servers