Webpack4文档

2,546 阅读5分钟

一、webpack基础介绍

1. webpack是什么?

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。

2. 为什么用webpack

原生浏览器,不能很好的识别 ES6 以及更高版本中ES moudule模块引入方式。代码中使用ES moudule ,可以通过webpack进行打包编译成浏览器识别的语法。

3、webpack安装使用的三种方式

  • global全局安装
// 全局安装
npm install webpack -g
// 全局下打包
webpack index.js
  • local项目安装
// 本地项目安装
npm install webpack --save-dev
// 本地项目打包
npx webapck index.js //直接执行 npx webpack 会调用默认配置文件 webpck.config.js
  • scripts配置安装
// scripts标签使用
"scripts": {
    "build": "webpack"
  },
// 本地项目打包
npm run build

4、webpack打包信息分析

二、loader

webpack处理js文件以外的文件时,就需要借助loader了

webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。

1、file-loader

将文件发送到输出文件夹,并返回(相对)URL。 可打包:图片、text等各种文件

2、url-loader

像 file loader 一样工作,但如果文件小于限制,可以返回 data URL 如果小于limit值,直接以base64形式打包到js中,大于和file-loader一样,生成文件。配合使用,优化。

3、style-loader

将模块的导出作为样式添加到 DOM 中

4、css-loader

解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码

// importLoaders 用于配置「css-loader 作用于 @import 的资源之前」有多少个 loader。
模块化打包css文件
use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2, // 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loader
            },
          },
          'postcss-loader',
          'sass-loader',
        ],
// modules 选项启用/禁用css模块规范和设置基本行为。
 options: {
          modules: true,
        },

5、postcss-loader

使用 PostCSS 加载和转译 CSS/SSS 文件

三、plugins

webpack 有着丰富的插件接口(rich plugin interface)。webpack 自身的多数功能都使用这个插件接口。这个插件接口使 webpack 变得极其灵活。

1、clean-webpack-plugin

A webpack plugin to remove/clean your build folder(s).

2、HtmlWebpackPlugin

简单创建 HTML 文件,用于服务器访问

3、SplitChunksPlugin

此配置对象表示splitchunksplugin的默认行为。

// webpack.config.js

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async', // 包括:all、async、initial(同步)
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      automaticNameMaxLength: 30,
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};

4. MiniCssExtractPlugin

这个插件将css提取到单独的文件中。它为每个包含css的js文件创建一个css文件。它支持按需加载css和sourcemap。
它建立在新的webpack v4特性(模块类型)之上,需要webpack 4才能工作。
extract-text-webpack-plugin相比:

  • Async loading
  • No duplicate compilation (performance)
  • Easier to use
  • Specific to CSS

TODO:

  • HMR support

四、开发环境下配置

1、devtool

此选项控制是否生成,以及如何生成 source map。

// 最佳实践:
development: cheap-module-eval-source-map
production: cheap-module-eval-source-map

2、webpack-dev-server

webpack-dev-server 为你提供了一个简单的 web server,并且具有 live reloading(实时重新加载) 功能。

注意:new HtmlWebpackPlugin( { // Also generate a test.html filename: 'index.html', // 使用webapck-dev-server打包至内存,需要index.html template: './index.html' } ),

3、HMR

模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新所有类型的模块,而无需完全刷新。

4、babel处理es6

  • 补充基础语法 桥梁:babel-loader @babel/core 处理:@babel/preset-env

五、优化

1、tree shaking

tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块语法的 静态结构 特性,例如 import 和 export。这个术语和概念实际上是由 ES2015 模块打包工具 rollup 普及起来的。

2、Code Splitting

代码分离是 webpack 中最引人注目的特性之一。此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。

常用的代码分离方法有三种

  • 入口起点:使用 entry 配置手动地分离代码。
  • 防止重复:使用 SplitChunksPlugin 去重和分离 chunk
  • 动态导入:通过模块中的内联函数调用来分离代码。

Code splitting这个概念一直都有,并非webpack独创,只是现在webpack将此功能集成了。 注意: webapck在做代码分割时,打包同步和异步引入的代码是有区别的。

  1. 打包同步代码时,只有在配置文件中做配置,webpack才会将类似lodash的库文件和业务代码做分割打包,否则会打包到一个文件中。
// 同步引入
import _ from 'lodash'
_.join(['a', 'b'], '?')

// webpack.config.js
optimization: {
        splitChunks: {
            chunks: "all"
        }
    },
  1. 打包异步引入的代码时,即使配置文件中没以设置,webpack也会默认将库文件和业务代码分开打包。
// 异步引入
function getComponent() {
    return import('lodash').then(({default: _}) => {
        var element = document.createElement('div')
        element.innerHTML = _.join(['a', 'b'], '?$')
        return element
    })
}

getComponent().then(element => {
    document.body.appendChild(element)
})
  1. Prefetching/Preloading

webpack v4.6.0+ 添加了预取和预加载的支持。

在声明 import 时,使用下面这些内置指令,可以让 webpack 输出 "resource hint(资源提示)",来告知浏览器:

  • prefetch(预取):将来某些导航下可能需要的资源
  • preload(预加载):当前导航下可能需要资源

与 prefetch 指令相比,preload 指令有许多不同之处:

  • preload chunk 会在父 chunk 加载时,以并行方式开始加载。
  • prefetch chunk 会在父 chunk 加载结束后开始加载。
  • preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。
  • preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk会用于未来的某个时刻。浏览器支持程度不同。

3、懒加载

懒加载或者按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。

4、Caching?既然contenthash变了,为什么浏览器访问,还是不是最新的?

Output Filenames

我们可以通过替换output.filename 中的 substitutions 设置,来定义输出文件的名称。webpack 提供了一种使用称为 substitution(可替换模板字符串) 的方式,通过带括号字符串来模板化文件名。其中,[contenthash] substitution 将根据资源内容创建出唯一 hash。当资源内容发生变化时,[contenthash] 也会发生变化。

5、Shimming

webpack compiler 能够识别遵循 ES2015 模块语法、CommonJSAMD 规范编写的模块。然而,一些 third party(第三方库) 可能会引用一些全局依赖(例如 jQuery 中的 $)。因此这些 library 也可能会创建一些需要导出的全局变量。这些 "broken modules(不符合规范的模块)" 就是 shim(预置依赖) 发挥作用的地方。

6、Environment Variables

想要消除 开发环境 和 生产环境 之间的 webpack.config.js 差异,你可能需要环境变量(environment variable)

webpack 命令行 环境配置 的 --env 参数,可以允许你传入任意数量的环境变量。而在 webpack.config.js 中可以访问到这些环境变量。例如--env.production--env.NODE_ENV=localNODE_ENV 通常约定用于定义环境类型,查看这里)。

webpack --env.NODE_ENV=local --env.production --progress