webpack 完全指南:核心概念

1,410 阅读4分钟

欲学 webpack,必会这几个核心概念:

  • entry(入口)
  • output(输出)
  • loader
  • plugin(插件)
  • mode(模式)

entry

entry 是用来指定 webpack 的打包入口。

entry 是 webpack 中一个很重要的概念,从 webpack 的构建机制来看,webpack 是一个模块打包器,也就是说它会将所有的资源(除了 js、css 等代码资源,也包括图片、字体依赖等非代码资源)都当成一个个的模块,而模块之间会存在一个依赖关系。所以,webpack 需要一个 入口文件 来进入这棵 依赖树(如下图):

01.png

用法

entry 的默认值是 ./src/index.js,我们可以 webpack 的配置文件中修改它。entry 会有两种情况:单入口 和 多入口。

单入口

单入口适用于 SPA(单页应用)的场景,值是一个字符串:

module.exports = {
  entry: "./src/index.js",
};

多入口

多入口适用于多页应用的场景,值是一个对象:

module.exports = {
  entry: {
    app: "./src/app.js",
    adminApp: "./src/adminApp.js",
  },
};

output

output 用于告诉 webpack 将编译后的文件存放到哪里,主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。

用法

单入口

在单入口的场景下,output 只需要简单指定一下文件名称( filename )和路径( path ):

const path = require('path');

module.exports = {
  //...
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, 'dist'),,
  },
};

多入口

不管是多少个入口文件( entry ),都只有一个 output,那么怎么确保文件名称的唯一性呢?利用占位符,比如 [name]

const path = require('path');

module.exports = {
  //...
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, 'dist'),,
  },
};

这里来举一个 🌰:

接上一篇文章的项目,我们改造为一个多页面应用。

  • 添加一个新入口 ./src/admin.js

    document.write("hello admin !");
    
  • 修改 webpack.config.js

    const path = require("path");
    
    module.exports = {
      entry: {
        index: "./src/index.js",
        admin: "./src/admin.js",
      }, // 多入口
      output: {
        filename: "[name].js", // 使用占位符
        path: path.resolve(__dirname, "dist"),
      },
      mode: "production",
    };
    
  • 删除原来的 dist(如果存在的话)

    rm -rf ./dist
    
  • webpack 打包

    npx webpack
    

    我们在 dist 文件夹中可以看到打包后的结果:

    01.png

Loader

原生的 webpack 仅支持 JS 和 JSON 两种文件类型(这是 webpack 开箱可用的自带能力),这对于现代的前端项目肯定是不够用的,那么对于 CSS、LESS、JSX、vue 等类型的文件该怎么办呢?

Loader 就是来帮助我们扩展 webpack,通过 Loader 可以支持 webpack 不支持的其他文件类型并且把它们转化为有效的模块,然后添加到依赖关系图中。

Loader 的本身是一个函数,接受源文件作为参数,最终返回转化的结果。

常见的 Loader

名称描述
babel-loader转换 ES6、ES7 等 JS 新特征语法
css-loader支持.css 文件的加载和解析
less-loader将 less 文件转换成 css 文件
ts-loader将 ts 文件转换成 js 文件
file-loader进行图片、字体等打包
raw-loader将文件以字符串的形式导入
thread-loader多进程打包 JS 和 CSS

用法

loader 的配置,我们放在一个单独的 module 对象的 rules 中,rules 作为一个数组可以添加多个 loader,通过两个属性配置 loader:

  • test 属性,指定匹配规则,识别出哪些文件会被转换。
  • use 属性,指定使用的 loader 名称,即在进行转换时,应该使用哪个 loader。

webpack.config.js:

const path = require("path");

module.exports = {
  // ...
  module: {
    rules: [{ test: /\.txt$/, use: "raw-loader" }],
  },
};

Plugin

Loader 用于处理 webpack 无法解析的文件,而 Plugin 则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。Plugin 就像是帮 Loader 完成了无法完成的事情,他可以作用于整个构建过程。

常见的 Plugin

名称描述
CommonsChunkPlugin多个页面打包,将 chunks 相同的模块代码提取成公共 js
CleanWebpackPlugin清理构建目录
ExtractTextWebpackPlugin将 CSS 从 bundle 文件中提取成一个独立的 CSS 文件
CopyWebpackPlugin将文件/文件夹拷贝到构建的输出目录去
HtmlWebpackPlugin创建 html 文件去承载输出的 bundle
UglifyjsWebpackPlugin压缩 JS
ZipWebpackPlugin将打包后的资源生成 zip 包

用法

在 webpack 配置中使用插件是简单直接的,想要使用一个插件,你只需要 require() 它,然后把它的实例(通过使用 new 操作符)添加到 plugins 数组中。

webpack.config.js:

const HtmlWebpackPlugin = require("html-webpack-plugin"); // 通过 npm 安装
const webpack = require("webpack"); // 用于访问内置插件

module.exports = {
  // ...
  plugins: [new HtmlWebpackPlugin({ template: "./src/index.html" })],
};

Mode

Mode 是用来指定当前的构建环境是:productiondevelopmentnone,默认值为 production。设置 mode 可以自动触发 webpack 的内置函数,比如 mode 为 development,那么 webpack 会自动开启在开发阶段更实用的参数/功能等,如果设置为 none,webpack 将不做任何操作。

Mode 的内置函数

选项描述
development设置 process.env.NODE_ENVdevelopment,开启 NamedChunksPluginNamedModulesPlugin(在热更新中,可以看到具体更新的模块)
production设置 process.env.NODE_ENVproduction,开启 FlagDependencyUsagePluginFlagIncludedChunksPluginModuleConcatenationPluginNoEmitOnErrorsPluginOccurrenceOrderPluginSideEffectsFlagPluginTerserPlugin
none不开启任何优化选项

webpack 系列