虽然webpack的已经升级到了webpack4,而我们目前还在使用webpack3,但其中的优化点都大同小异,升级后同样适用。

性能优化初步原则

  • 减小代码量

  • 减小请求数

  • 最大化利用浏览器缓存

这三条原则永远是一切优化的前提

优化配置

  • 升级webpack 3,优化js的编译能力(Scope Hoisting)

1// 主要配置
2plugins:[
3  new webpack.optimize.ModuleConcatenationPlugin()
4]
  • 合理规划 entry 入口配置(平衡vendor.js, app.js文件的大小)

 1// main.js中第三方公共库提出,作为公共vendor.js, 配合package.json固定第三方库版本,最大化利用浏览器缓存加载js
2entry: {
3  vendor:['vue', 'vue-router', 'vue-resource'],
4  app: './src/main.js'
5}
6// ...
7plugins:[
8  new webpack.optimize.CommonsChunkPlugin({
9    name: ['manifest','vendor'].reverse(),
10    minChunks:Infinity
11  })
12]
  • 打包后文件大小限制,首次加载js+css超过 400k,单个文件大小超过 300k将会报错,打包不通过,该配置在build中使用

1performance: {
2  hints: 'error',
3  maxEntrypointSize: 400000,
4  maxAssetSize: 300000
5}

减小代码量

  • 提取 chunk 中使用的公共库(能为chunk代码节约近1/3的代码量)

1new webpack.optimize.CommonsChunkPlugin({
2  name: 'app',
3  async: 'vendor-async',
4  children: true,
5  minChunks: (module, count) => {
6    // 被 2 个及以上 chunk 使用的共用模块提取出来
7    return count >= 2
8  }
9})
  • 减少图片base64的使用,降低限制,限制2k(vue官方配置是10k,会大大增加js文件体积,移动端对base64的解析成本高)

1  {
2    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
3    loader: 'url-loader',
4    options: {
5      limit: 2048,
6      name: utils.assetsPath('img/[name].[hash:7].[ext]')
7    }
8  }
  • 生产模式(pro)下第三方库使用已压缩版本,能节约近20k文件大小

 1// 开发模式
2resolve: {
3  alias: {
4    'vue': 'vue/dist/vue.esm.js'
5  }
6}
7// 生产模式
8resolve: {
9  alias: {
10    'vue': 'vue/dist/vue.min.js'
11  }
12}
  • 优化 babel-ployfill,结合 babel-preset-env 实现兼容按需加载,比使用es2015能节约近半的大小

1entry: {
2  vendor:['babel-polyfill', 'vue', 'vue-router', 'axios'],
3  app: './src/main.js'
4}
 1// .babelrc
2{
3  "presets": [
4    ["env", {
5      "modules": false,
6      "targets": {
7        "browsers": [
8          "> 1%",
9          "last 3 versions",
10          "Firefox ESR",
11          "not ie < 10"
12        ]
13      },
14      "debug": false,
15      "useBuiltIns": true
16    }],
17    "react",
18    "stage-2"
19  ]
20}
  • 极致压缩js,css代码

 1var os = require('os')
2var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
3
4plugins: [
5  new webpack.optimize.UglifyJsPlugin({
6    // 利用多核能力压缩
7    beautify: {
8      cache: true,
9      workers: os.cpus().length
10    },
11    // 最紧凑的输出
12    beautify: false,
13    // 删除所有的注释
14    comments: false,
15    compress: {
16      // 在UglifyJs删除没有用到的代码时不输出警告
17      warnings: false,
18      // 删除所有的 `console` 语句
19      drop_console: true,
20      // 内嵌定义了但是只用到一次的变量
21      collapse_vars: true,
22      // 提取出出现多次但是没有定义成变量去引用的静态值
23      reduce_vars: true,
24    },
25    sourceMap: true
26  }),
27  new OptimizeCSSPlugin({
28       cssProcessor: require('cssnano')({ zindex: false }),
29    cssProcessorOptions: {
30      safe: true,
31      discardComments: {removeAll: true }
32    }
33  })
34]
  • 第三方库的依赖过滤,如下:

1// 此插件默认全部引入语言库,但我们只用到了中文,最多英文,所以进行了过滤,大大减少了总体代码量
2plugins: [
3  new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /zh|en/)
4]

减少请求数

  • manifest.js文件内联(app.css可以自行选择,当小于10k是最好内联),webpack推荐配置如下:

 1// 引入内联插件
2var HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin')
3
4plugins:[
5  // ...
6  new HtmlWebpackPlugin({
7    // ... 其他不相关配置省略
8    inlineSource:/(app\.(.+)?\.css|manifest\.(.+)?\.js)$/,
9    // ...
10  }),
11  new HtmlWebpackInlineSourcePlugin()
12]

最大化利用浏览器缓存

这样能最大化利用浏览器缓存

 1// 不固定版本,会造成打包后 hash 值变化,浏览器没办法利用本身的缓存加载js,每次上线都会使本地缓存失效,页面加载变慢
2"dependencies": {
3  "moment": "2.17.1",
4  "querystring": "0.2.0",
5  "sprite-cli": "0.1.5",
6  "sticky-state": "2.4.1",
7  "superagent-jsonp": "0.1.1",
8  "underscore": "1.8.3",
9  "vue": "2.0.0",
10  "vue-lazyload": "0.8.3",
11  "vue-router": "2.0.0",
12  "vuex": "2.0.0"
13}

其他优化

zindex被重置问题

由于cssnano默认配置,是自动会把z-index重置为1,例如:

1classname {
2    z-index:1000;
3}
4
5after
6
7classname {
8    z-index:1;
9}

这时候需要优化cssnano的配置,.postcssrc 如下:

 1/* eslint-disable no-unused-vars */
2module.exports = {
3  plugins: {
4    cssnano: {
5      preset: [
6        'advanced',
7        {
8          zindex: false,
9        }
10      ]
11    }
12  }
13}

使用按需加载js后,打包代码特别大

需要注意的是,当使用按需加载的功能,然后没有提取所有chunk包里的css,同时又开启了sourcemap功能,那么就会造成这种情况
最简单的办法就是,对css不使用sourcemap功能,例如:

1rules: [
2  {
3    loader: 'postcss-loader',
4    options: {
5      sourceMap: false
6    }
7  }
8]

广告

以下是笔者基于 vue-cli 的模版优化后的vue和react的打包工具,用法一致。

以下包集成了以上所有优化,支持单页面及多页面应用,完全兼容vue-cli生成的模版项目

zz-webpack-vue

zz-webpack-react

以下是使用本组一个vue-cli生成的项目做的一个优化对比:

优化前:

打包

分析

优化后:

打包

分析

可以查看具体的优化配置,或者直接在项目中尝试使用,有任何问题欢迎随时反馈,目前正在筹划统一升级webpack4

(webpack系列二)webpack打包优化探索的更多相关文章

  1. webpack系列--浅析webpack的原理

    一.前言 现在随着前端开发的复杂度和规模越来越大,鹰不能抛开工程化来独立开发,比如:react的jsx代码必须编译后才能在浏览器中使用,比如sass和less代码浏览器是不支持的.如果摒弃这些开发框架 ...

  2. Vue+Webpack之 代码及打包优化

    本文重点介绍Vue单页面应用的优化手段: 异步加载 面切换时加loading特效 点击延迟 inline manifest 逻辑代码优化 依赖包体积优化 cdn引用 Vue代码优化 异步加载 所谓的异 ...

  3. webpack系列:webpack小老弟接了个简单活

    webpack深入浅出系列:进阶篇 前沿,本篇文章的讲解思路是以webpack的五大核心为线索,以webpack对象为第一视角来讲述(以前记得看过一个文笔非常厉害的技术啊婆写的,非常有趣.然后我就想着 ...

  4. webpack教程(二)——webpack.config.js文件

    首先我们需要安装一个webpack插件html-webpack-plugin,该插件的作用是帮助我们生成创建html入口文件.执行如下命令 npm install html-webpack-plugi ...

  5. WebPack系列:Webpack编译的代码如何在tomcat中使用时静态资源路径不对的问题如何解决

    问题:     使用webpack+vue做前端,使用tomcat提供api,然后npm run build之后需要将编译,生成如下文件: |   index.html \---appserver   ...

  6. webpack 打包优化的四种方法(多进程打包,多进程压缩,资源 CDN,动态 polyfill)

    如今,webpack 毫无疑问是前端构建领域里最耀眼的一颗星,无论你前端走哪条路线,都需要有很强的webpack 知识.webpack 的基本用法这里就不展开讲了.主要探讨一下如何提高 webpack ...

  7. 记一次webpack打包优化

    未进行打包优化的痛点: 随着项目的不断扩大,引入的第三方库会越来越多,我们每次build的时候会对所有的文件进行打包,耗时必定很长,不利于日常开发. 解决思路: 第三方库我们只是引入到项目里来,一般不 ...

  8. vue-cli内部webpack的打包优化

    在此之前,我们先谈谈前端项目的性能优化. 优化前端项目无非就是2方面的优化: 一.网络性能优化(重点) 减少请求数量(webpack的天职就是打包) 减少请求资源大小(压缩gzip,后端会完成) CD ...

  9. webpack原理探究 && 打包优化

    在做vue项目和react项目时,都用到了webpack.webpack帮助我们很好地提高了工作效率,但是一直以来没有对其原理进行探究,略有遗憾. 因为使用一个工具,能够深入了解其原理才能更好地使用. ...

随机推荐

  1. js设置高度和宽度相等

    <!doctype html><html><head><meta charset="utf-8"><link rel=&quo ...

  2. Java 日志体系(二)jcl 和 slf4j

    Java 日志体系(二)jcl 和 slf4j <java 日志体系(一)统一日志>:https://www.cnblogs.com/binarylei/p/9828166.html &l ...

  3. Qt自定义滚动条(不使用样式表)

    前面使用Qt 样式表实现滚动条,在实际工作中,发现存在一些瑕疵,例如如果在主窗口中绘制背景,则有可能给滚动条染色,还有如果想实现特殊的效果,则必须使用自定义风格,即从QStyle的子类派生出新的类型. ...

  4. 【Selenium】【BugList6】调用IE,未启用保护模式,报:selenium.common.exceptions.WebDriverException: Message: Unexpected error launching Internet Explorer. Protected Mode settings are not the same for all zones.

    >>> driver = webdriver.Ie() 解决方法: 1.打开Ie浏览器 , 工具 ->Internet选项 ->安全 2.去掉4个区域的安全保护模式

  5. 磨人的Fragment的转换

    磨人的Fragment的转换 本次任务是 程序运行之后将第一个Fragment加载出来 然后点击"SHOW NEXT PAGE"切换到第二个Fragment 当再次点击按钮时下方出 ...

  6. spring深入学习(二)-----bean的生命周期、IOC容器bean装配

    bean的生命周期 1.实例化Bean对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBea ...

  7. shell脚本学习-循环

    跟着RUNOOB网站的教程学习的笔记 for循环 与其他编程语言类似,shell支持for循环. for循环一般格式为: for var in item1 item2 ... itemN do com ...

  8. Java Web服务器的联机交易

    我们知道服务器可以对外部的请求进行应答 ,在BS架构中,通过浏览器可以向Apache Tomcat或者WebSphere服务器发送请求.但是可能存在请求的渠道不是浏览器的情况,他有可能是另外一个jav ...

  9. 网页偶现性崩溃-chrome

    简介: 项目前台框架:Angular2 + Bootstrap(日期等组件) + Echarts + 响应式(包括页面.字体缩放:rem) chrome版本:多个版本测试均有此问题. 表现: 订单详情 ...

  10. VUE最佳实践

    vuex 作为model数据请求由action来获取,页面组建级的发送action,返回promise给组建使用,如果使用周期较长需comit到mutation保存到state. 数据分模块,根据业务 ...