使用Webpack4优化Web性能(一)

webpack.png

利用 Webpack 来优化 Web 性能属于_加载性能优化_的一部分: ☛ Web Performance Optimization with webpack

1、减小前端资源体积

一、webpack 4 开启production模式

production模式下 webpack 会对代码进行优化,如减少代码体积,删除只在开发环境用到的代码。

能够在 webpack 中指定:css

module.exports = {
  mode: 'production' // 或 development
};

或者 package.json 中配置:前端

"scripts": {
    "dev": "webpack-dev-server --mode development --open --hot",
    "build": "webpack --mode production --progress"
}

二、压缩代码

使用 bundle-level minifier 和 loader options 压缩代码。
  • Bundle-level minification

Bundle-level 的压缩会在代码编译后对整个包进行压缩。react

在 webpack 4 中,production 模式下会自动执行 bundle-level 的压缩,底层使用了 the UglifyJS minifier。(若是不想开启压缩,能够采用 development 模式或者设置 optimization.minimize 为 false)webpack

  • Loader-specific options

经过 loader 层面的选项配置来对代码进行压缩,是为了压缩 bundle-level minifier 没法压缩的内容,好比,经过 css-loader 编译后的文件,会成为字符串,就没法被 minifier 压缩。所以,要进一步压缩文件内容,可进行以下配置:git

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          { loader: 'css-loader', options: { minimize: true } },
        ],
      },
    ],
  },
};

三、使用 ES 模块

当使用 ES 模块时, webpack 可以进行 tree-shaking。

tree-shaking 是指 bundler 遍历整个依赖关系树,检查使用了哪些依赖关系,并删除未使用的依赖关系。所以,若是使用ES模块语法,webpack 能够消除未使用的代码。github

★ 注意:在 webpack 中,若是没有 minifier,tree-shaking 就没法工做。webpack 只删除不使用的导出语句,而 minifier 则会删除未使用的代码。所以,若是在编译时不使用 minifier,代码量并不会减少。(除了使用 wbpack 内置的 minifier,其它的插件如 Babel Minify plugin 也能对代码进行压缩)。web

✘ 警告:不要意外地将 ES 模块编译成 CommonJS 模块。若是你使用 Babel 的时候,采用了 babel-preset-env 或者 babel-preset-es2015,请检查这些预置的设置。默认状况下,它们会将 ES 的导入和导出转换为 CommonJS 的 requiremodule.exports,能够经过传递 { modules: false } 选项来禁用它。json

Introduction to ES Modules
一口(很长的)气了解 babel
➹ Webpack docs about tree shaking浏览器

四、压缩图片资源

针对具体的依赖项进行优化( dependency-specific optimization

图像占了页面大小的一半以上。虽然它们不像JavaScript那样重要(例如,它们不会阻塞呈现),但它们仍然占用了很大一部分带宽。在 webpack 中可使用 url-loadersvg-url-loaderimage-webpack-loader 来优化它们。性能优化

url-loader 能够将小型静态文件内联到应用程序中。若是不进行配置,它将把接受一个传递的文件,将其放在已编译的包旁边,并返回该文件的url。可是,若是指定 limit 选项,它将把小于这个限制的文件编码为Base64 数据的 url 并返回这个url,这会将图像内联到 JavaScript 代码中,从而能够减小一个HTTP请求。

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif)$/,
        loader: 'url-loader',
        options: {
          // Inline files smaller than 10 kB (10240 bytes)
          limit: 10 * 1024,
        },
      },
    ],
  }
};
// index.js
import imageUrl from './image.png';
// → If image.png is smaller than 10 kB, `imageUrl` will include
// the encoded image: 'data:image/png;base64,iVBORw0KGg…'
// → If image.png is larger than 10 kB, the loader will create a new file,
// and `imageUrl` will include its url: `/2fcd56a1920be.png`

★ 注意:须要在增大代码体积和减小 HTTP 请求数以前进行权衡。

svg-url-loader 的工做原理与 url-loader 相似 — 只是它使用的是URL编码而不是Base64编码来编码文件。这对SVG图像颇有用 — 由于SVG文件只是纯文本,这种编码更高效。

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        loader: 'svg-url-loader',
        options: {
          // Inline files smaller than 10 kB (10240 bytes)
          limit: 10 * 1024,
          // Remove the quotes from the url
          // (they’re unnecessary in most cases)
          noquotes: true,
        },
      },
    ],
  },
};

★ 注意: svg-url-loader 有一些选项能够改进Internet Explorer的支持,但会使其余浏览器的内联更加糟糕。若是须要支持此浏览器,请应用 iesafe: true 选项。

image-webpack-loader 可支持JPG、PNG、GIF和SVG图像的压缩。

这个加载器不嵌入图像到应用程序,因此它必须与 url-loadersvg-url-loader 成对工做。为了不将其复制粘贴到两个规则中(一个用于JPG/PNG/GIF图像,另外一个用于SVG图像),咱们经过 enforce: 'pre' 将这个加载器设为一个单独的规则:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/,
        loader: 'image-webpack-loader',
        // This will apply the loader before the other ones
        enforce: 'pre',
      },
    ],
  },
};

五、优化第三方依赖

JavaScript 的大小平均有一半以上来自依赖项,而其中的一部分多是没必要要的。咱们能够对这些依赖的库进行优化➡️ webpack-libs-optimizations

好比:moment.js 删除未使用的地区、react-router 移除未使用的模块,生产环境去除 react propTypes 声明等。

六、对于ES6模块开启模块链接

也叫作做用域提高(Scope Hoisting)

早期的时候,为了隔离 CommonJS/AMD 模块,webpack 在打包的时候,会把每一个模块都打包到一个函数中,这样就会增大每一个模块的大小和性能开销。webpack 2 的时候支持了 ES 模块,而后 webpack 3 的时候使模块链接成为了可能。

【原理】:它会分析模块间的依赖关系,尽量将被打散的模块合并到一个函数中,但不能形成代码冗余,因此只有被引用一次的模块才能被合并。因为须要分析模块间的依赖关系,因此源码必须是采用了ES6模块化的,不然Webpack会降级处理不采用Scope Hoisting。

开启模块链接以后,打出的包将会具备更少的模块,以及更少的模块开销。若是在生产模式下使用 webpack 4,则模块链接已经启用。

// webpack.config.js (for webpack 4)
module.exports = {
  optimization: {
    concatenateModules: true,
  },
};

★ 注意:为何默认状况下不启用此行为?链接模块很酷,可是它增长了构建时间,并中断了热模块替换。这就是为何应该只在生产中启用它。

三十分钟掌握Webpack性能优化

七、若是以为有意义的话,使用 externals

具体请参考:webpack-configuration-externals

相关文章
相关标签/搜索