• 打包速度:优化打包速度,主要是进步了咱们的开发功率,更快的打包构建过程,将让你保持一颗愉悦的心
  • 打包体积:优化打包体积,主要是进步产品的运用体验,降低服务器资源成本,更快的页面加载,将让产品显得更加“丝滑”,同时也能够让打包更快

webpack 打包速度优化

webpack 进行打包速度优化有七种常用手段

1. 优化 loader 查找规模

关于 loader 来说,影响打包功率首战之地必属 Babel 了。因为 Babel 会将代码转为字符串生成 AST,然后对 AST 继续进行改变最后再生成新的代码,项目越大,转换代码越多,功率就越低。优化正则匹配、运用 include 和
exclude 指定需求处理的文件,疏忽不需求处理的文件

rules: [{
    // 优化正则匹配
    test: /.js$/,
    // 指定需求处理的目录
    include: path.resolve(__dirname, 'src')
    // 理论上只有include就够了,可是某些状况需求排除文件的时分能够用这个,排除不需求处理文件
    // exclude: []
}]

2. 多进程/多线程

受限于 node 是单线程运行的,所以 webpack 在打包的过程中也是单线程的,特别是在执行 loader 的时分,长期编译的任务
许多,这样就会导致等候的状况。咱们能够运用一些方法将 loader 的同步执行转换为并行,这样就能充分利用系统资源来进步
打包速度了

{
  test: /.js?$/,
  exclude: /node_modules/,
  use: [
    {
      loader: "thread-loader",
      options: {
        workers: 3 // 进程 3 
      }
    },
    {
    loader: "babel-loader",
    options: {
      presets: ["@babel/preset-env"],
      plugins: ["@babel/plugin-transform-runtime"]
      }
    }
  ]
},

3. 分包

在运用 webpack 进行打包时分,关于依靠的第三方库,比方 vue,vuex 等这些不会修改的依靠,咱们能够让它和咱们自己编写
的代码分隔打包,这样做的好处是每次更改我本地代码的文件的时分,webpack 只需求打包我项目本身的文件代码,而不会再
去编译第三方库,那么第三方库在第一次打包的时分只打包一次,以后只需咱们不升级第三方包的时分,那么 webpack 就不会
对这些库去打包,这样能够快速进步打包的速度。因而为了解决这个问题,DllPlugin 和 DllReferencePlugin 插件就产生了。这种
方法能够极大的削减打包类库的次数,只有当类库更新版本才需求从头打包,而且也完成了将公共代码抽离成独自文件的优化方案

// webpack.dll.conf.js
const path = require('path')
const webpack = require('webpack')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
    mode: 'production',
    devtool: false,
    entry: {
        vue: [
            'vue',
            'vue-router',
            'iscroll',
            'vuex'
        ],
    },
    output: {
        path: path.join(__dirname, '../dist'),
        filename: 'lib/[name]_[hash:4].dll.js',
        library: '[name]_[hash:4]'
    },
    performance: {
        hints: false,
        maxAssetSize: 300000, //单文件超越300k,命令行告警
        maxEntrypointSize: 300000, //初次加载文件总和超越300k,命令行告警
    },
    optimization: {
        minimizer: [
            new UglifyJsPlugin({
                parallel: true // 敞开多线程并行
            })
        ]
    },
    plugins: [
        new webpack.DllPlugin({
            context: __dirname,
            path: path.join(__dirname, '../dist/lib', '[name]-manifest.json'),
            name: '[name]_[hash:4]'
        })
    ]
}
// webpack.prod.cong.js
plugins: [
    new webpack.DllReferencePlugin({
        context: __dirname,
        manifest: require('../dist/lib/vue-manifest.json')
    }),
]

4. 敞开缓存

当设置 cache.type:“filesystem”时,webpack 会在内部以分层方法启用文件系统缓存和内存缓存,将处理结果结存放到内存中,
下次打包直接运用缓存结果而不需求从头打包

{
    type: "filesystem",
    // cacheDirectory 默许途径是 node_modules/.cache/webpack
    // cacheDirectory: path.resolve(__dirname, '.temp_cache')
}

5. 打包剖析东西

显示测量打包过程中各个插件和 loader 每一步所耗费的时刻,然后让咱们能够有针对的剖析项目中耗时的模块对其进行处理。

npm install speed-measure-webpack-plugin -D
// webpack.prod.config.js
const SpeedMeatureWebpackPlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeatureWebpackPlugin();
var webpackConfig = merge(baseWebpackConfig,{})
--> 修改为下面格局
var webpackConfig = {...}
module.exports = webpackConfig
--> 修改为下面格局
module.exports = smp.wrap(merge(baseWebpackConfig, webpackConfig));

6. ignorePlugin

这是 webpack 内置插件, 它的效果是疏忽第三方包指定目录,让这些指定目录不要被打包进去,防止在 import 或 require 调用时,生成以下正则表达式匹配的模块

  • requestRegExp 匹配( test )资源恳求途径的正则表达式。
  • contextRegExp( 可选 )匹配( test )资源上下文( 目录 )的正则表达式
new webpack.IgnorePlugin({
   resourceRegExp: /^./test$/,
   contextRegExp: /test$/,
})

7. 优化文件途径

  • alias:省下查找文件的时刻,让 webpack 更快找到途径
  • mainFiles:解析目录时要运用的文件名
  • extensions:指定需求查看的扩展名,装备之后能够不用在 require 或是 import 的时分加文件扩展名,会顺次尝试增加扩展名进行匹配
resolve: {
   extensions: ['.js', '.vue'],
   mainFiles: ['index'],
   alias: {
       '@': resolve('src'),
       }
   }

webpack 打包体积优化

webpack打包体积优化有11种常用优化手段

1. 构建体积剖析

npm run build 构建,会默许翻开: http://127.0.0.1:8888/,能够看到各个包的体积,剖析项目各模块的巨细,能够按需优化。

npm install webpack-bundle-analyzer -D
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
plugins:[
    new BundleAnalyzerPlugin()
]
  1. 项目图片资源优化紧缩处理
    对打包后的图片进行紧缩和优化,降低图片分辨率,紧缩图片体积等
npm install image-webpack-loader -D
// webpack.base.conf.js
   {
       test: /.(gif|png|jpe?g|svg|webp)$/i,
       type: "asset/resource",
       parser: {
       dataUrlCondition: {
       maxSize: 8 * 1024
       }
   },
   generator: {
      filename: "images/[name].[hash:6][ext]"
   },
   use: [
      {
         loader: "image-webpack-loader",
         options: {
            mozjpeg: {
               progressive: true,
               quality: 65
            },
            optipng: {
               enabled: false
            },
            pngquant: {
               quality: [0.5, 0.65],
               speed: 4
            },
            gifsicle: {
               interlaced: false
            },
            webp: {
               quality: 75
            }
         }
      }
   ]
   }

3. 删去无用的 css 款式

有时分一些项目中可能会存在一些 css 款式被迭代废弃,需求将其删去,能够运用 purgecss-webpack-plugin插件,该插件能够去
除未运用的 css。

npm install purgecss-webpack-plugin glod -D
// webpack.prod.conf.js
const PurgeCSSPlugin = require("purgecss-webpack-plugin");
const glob = require('glob')
const PATHS = {
   src: path.join(__dirname, 'src')
}
// plugins
new PurgeCSSPlugin({
   paths: glob.sync(`${PATHS.src}/**/*`, {nodir: true}),
   safelist: ["body"]
}),

4. 代码紧缩

对 js 文件进行紧缩,然后减小 js 文件的体积,还能够紧缩 html、css 代码。

const TerserPlugin = require("terser-webpack-plugin");
optimization: {
   minimize: true, //代码紧缩
   usedExports:true, // treeshaking
   minimizer:
      [
         new TerserPlugin({
            terserOptions: {
               ecma: undefined,
               parse: {},
               compress: {},
               mangle: true, // Note `mangle.properties` is `false` by default.
               module: false,
               // Deprecated
               output: null,
               format: null,
               toplevel: false,
               nameCache: null,
               ie8: false,
               keep_classnames: undefined,
               keep_fnames: false,
               safari10: false
            }
         })
      ],
   splitChunks:
      {
         cacheGroups: {
            commons: {
               name: "commons",
               chunks: "initial",
               minChunks: 2
            }
         }
      }
}

5. 敞开 Scope Hoisting

Scope Hoisting又译作“效果域进步”。只需在装备文件中增加一个新的插件,就能够让 webpack 打包出来的代码文件更小、运行
的更快, Scope Hoisting会剖析出模块之间的依靠关系,尽可能的把打包出来的模块合并到一个函数中去,然后适当地重命名一
些变量以防止命名抵触。
new webpack.optimize.ModuleConcatenationPlugin();

6. 提取公共代码

将项目中的公共模块提取出来,能够削减代码的冗余度,进步代码的运行功率和页面的加载速度。
new webpack.optimize.CommonsChunkPlugin(options);

7. 代码别离

代码别离能够将工程代码别离到各个文件中,然后按需加载或并行加载这些文件,也用于获取更小的 bundle,以及操控资源加
载优先级,在装备文件中装备多进口,输出多个 chunk。
//多进口装备 终究输出两个chunk

module.exports = {
   entry: {
      index: 'index.js',
      login: 'login.js'
   },
   output: {
      //关于多进口装备需求指定[name]不然会呈现重名问题
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist')
   }
};

8. Tree-shaking

treeshaking是一个术语,一般用于描述移除 JavaScript 上下文中的未引证代码( dead-code )。它依靠于 ES2015 模块语法的 静
态结构 特性,例如 import 和 export。

9. CDN 加快

CDN 的全称是 Content DeliveryNetwork,即内容分发网络。CDN 是构建在网络之上的内容分发网络,依靠部署在各地的边际
服务器,经过中心平台的负载均衡、内容分发、调度等功能模块,运用户就近获取所需内容,降低网络拥塞,进步用户访问响
应速度和命中率。CDN 的关键技能主要有内容存储和分发技能。在项目中以 CDN 的方法加载资源,项目中不需求对资源进行
打包,大大削减打包后的文件体积

10. 出产环境封闭 sourceMap

sourceMap 本质上是一种映射关系,打包出来的 js 文件中的代码能够映射到代码文件的具体位置,这种映射关系会协助咱们直接找到在源代码中的错误。但这样会使项目打包速度减慢,项目体积变大,能够在出产环境封闭 sourceMap

11. 按需加载

在开发项目的时分,项目中都会存在十几甚至更多的路由页面。假如咱们将这些页面悉数打包进一个文件的话,虽然将多个请
求合并了,可是同样也加载了许多并不需求的代码,耗费了更长的时刻。那么为了页面能更快地呈现给用户,咱们肯定是希望
页面能加载的文件体积越小越好,这时分咱们就能够运用按需加载,将每个路由页面独自打包为一个文件。以下是常见的按需
加载的场景

* 路由组件按需加载
* 按需加载需引进第三方组件
* 关于一些插件,假如只是在个别组件顶用的到,也能够不要在 main.js 里边引进,而是在组件中按需引进