Webpack知识体系 | 青训营笔记

99 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的的第16天

字节跳动青训营范文杰老师的课

一.什么是 Webpack

前端项目由各式各样的资源组成,包括 png,js,ts,jsx,vue,css,less 等等,早期项目需要手动通过 script,img 等标签来引入各种文件。

外部资源特别多时,我们需要手动管理,要考虑文件顺序等问题,特别容易出错。这样做影响了开发效率,限制了项目的规模。

为了解决这些问题,出现了很多工程化工具。正是因为这些工具的出现,有了前端工程化的概念。

Webpack 是前端资源的编译和打包工具。

编译是为了将图片、less、sass、ts 等非 JS 文件转变成标准的 JS 内容。之后将编译好的内容打包成一个文件 bundle。Webpack 刚出现的时候,浏览器不支持 ESM 模式,当时将资源放到浏览器运行需要逐个引入 script,使用 Webpack 打包好后只需要插入一个 script。

二.使用Webpack

示例

使用 Webpack 主要分三步:安装、编辑配置文件、执行编译命令。

  1. 安装

npm i -D webpack webpack-cli

  1. 编辑配置文件
// webpack.config.js
const path = require('path')

module.exports = {
  // 打包的入口
  entry: './src/index',
  // 打包模式 development 和 production,默认为 production
  mode: 'development',
  devtool: false,
  // 打包的出口
  output: {
    filename: '[name].js',
    path: path.join(__dirname, './dist')
  }
}
  1. 执行编译命令

npx webpack

待编译的文件:

// src/index.js
import bar from './bar'

console.log(`hello ${bar}`)

// src/bar.js
export default 'bar'

编译的结果:

// dist/main.js
// ...
__webpack_require__.r(__webpack_exports__);
// ...
const __WEBPACK_DEFAULT_EXPORT__ = ('bar')
// ...
console.log(`hello ${_bar__WEBPACK_IMPORTED_MODULE_0__["default"]}`)

打包后 import 语句会转为 webpack_require 语句,两个文件被合并为一个。

核心流程

资源解析就是调用 loader 的过程。

Webpack 主要做两件事情:模块化、一致性。

模块化是指将不同类型的文件都用 import 和 require 来管理,

一致性是指 Webpack 支持非 JS 语言,像 TypeScript,图片,CSS,字体等资源的合并打包。

(核心流程简化版)

怎么使用

配置分类

关于Webpack的使用方法,基本都围绕“配置”展开,而这些配置大致可划分为两类:

流程类:作用于流程中某个or若干个环节,直接影响打包效果的配置项

工具类:主流程之外,提供更多工程化能力的配置项

流程类配置图

配置总览

文件结构

1. 处理 CSS

1.安装 loader

npm add -D css-loader style-loader

2.添加 module 处理 CSS 文件

// webpack.config.js
const path = require('path')

module.exports = {
  // ...
  module: {
    rules: [{
      // 过滤条件,满足 test 规则的才使用 rule 处理
      test: /.css$/,
      // 用什么 loader 去处理满足 test 的文件
      use: ["style-loader", "css-loader"]
    }]
  }
}

3.执行 npx webpack

待处理的文件:

// index.js
import styles from './index.css'

2. 接入 Babel

Babel 是代码转译工具,用于将 ES6 的代码编译成 ES5 的代码。

  1. 安装依赖

npm i -D @babel/core @babel/preset-env babel-loader

2.声明产物出口 output

const path = require("path");
module.exports = {
  entry: "./src/index",
  output: {
    filename: " [ name].js",
    path: path.join(__dirname, "./dist"),
  },
  module: {
    rules: [{
      test: /.js?$/,
      use: [{
        loader: ' babel-loader',
        options: {
          presets: [
          // preset 是提前打包好的规则集
            ['@babel/preset-env']
          ]
        }
      }]
    }],
  },
};

3.执行 npx webpack

3. 生成 HTML

使用插件自动生成 HTML 文件。

1.安装依赖

npm i -D html-webpack-plugin

2.声明产物出口 output

const path = require("path");
const HtmlwebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: "./src/index",
  output: {
    filename: "[name].js",
    path: path.join(__dirname, " ./dist"),
  },
  // 生成 HTML
  plugins: [new HtmlwebpackPlugin()]
};

3.执行 npx webpack

4. HMR

HMR 是指 Hot Module Replacement 模块热替换,编写的代码可以立刻被更新到浏览器上,不需要刷新。

  1. 开启 HMR
module.exports = {
  // ...
  devServer: {
    // 开启 HMR
    hot: true
  }
  // webpack 持续监听文件的变化并持续构建
  watch: true
};

2.启动 Webpack

npx webpack serve

5. Tree-Shaking

用于删除 dead code,也就是没有用到的代码。

module.exports = {
  // ...
   mode: "production"
   optimization {
     usedExports: true
   }
 };

理解 Loader

Webpack 只认识 JS,Loader 的作用是做内容的转换,它将非标准的 JS 资源翻译为标准 JS。

使用 Loader:处理 less 文件

  1. 安装 Loader

npm add -D css-loader style-loader less-loader

2.添加 module 处理 less 文件

module.exports = {
  module: {
    rules: [{
      test: /.less$/i,
      use: ["style-loader", "css-loader", "less-loader"],
    }],
  },
};

这三个 loader 符合链式调用的规则:

  • less-loader:实现 less => CSS 的转换
  • css-loader:将 CSS 包装成类似 module.exports = "${css]" 的内容,包装后的内容符合 JavaScript 语法
  • style-loader:将 CSS 模块包进 require 语句,并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签

其他特性:

链式执行;支持异步执行;分 normal、pitch 两种模式。

执行阶段从数组的最后一位向前进行。

编写 Loader:

// loader.js
module.exports = function (source, sourceMap?, data?) {
  // source 为 loader 的输入
  //可能是文件内容,也可能是上一个 loader 处理结果
  return source;
};

理解插件

使用插件的目的是提升应用的可扩展性,体现了对拓展开放、对修改关闭的思维。插件是在 Webpack 的整个生命周期都会生效的组件。

使用插件:Dashboard

// npm i -D webpack-dashboard
// Import the plugin:
const DashboardPlugin = require("webpack-dashboard/plugin");
// Add it to your webpack configuration plugins.
module.exports = {
  // ...
  plugins: [new DashboardPlugin()]
  //...
};

编写插件的过程围绕钩子展开,包括钩子的时机、上下文、交互。

学习 Webpack

Webpack 入门的关键知识点: