今天我学会webpack了吗? --【基础篇 2】输入 & 输出

270 阅读4分钟

对 webpack 的打包有了一个基础的体验之后,可以开始尝试自定义一些配置了。

在开始配置之前,先了解一下 webpack 的四个核心概念。

webpack的四个核心概念

即 entry (入口)、output (出口)、loader (模块转换器)、plugin (插件)

  • entry (入口)

告诉 wbpack 要使用哪个文件作为构建项目的起点。默认为 ./src/index.js

webpack 从入口开始,根据模块间的依赖关系,递归解析和处理所有资源文件。

  • output (出口)

告诉 webpack 打包后的文件名和路径。

主要输出文件默认为 ./dist/main.js,其他文件放在 ./dist 文件夹中。

module.exports = {
  mode: 'development',
  entry: path.resolve(__dirname, '../src/index.js'),
  output: {
    filename: '[name].[hash:8].js',
    path: path.resolve(__dirname, '../dist'),
  },
}
  • loader (模块转换器)

实现对不同格式文件的处理,比如,将 sass 转换为 css,将 typescript 转换为 js 等。

转换这些文件,从而使其能够被添加到依赖图中。

为什么要转换?

原因是,webpack 本身只理解 javascript 和 JSON 文件,别的认不得,所以需要 loader 来“翻译”一下。

loader 本质是一个函数,对接收到的内容进行转换,返回转换后的结果。

  • plugin (插件)

即扩展插件。插件可以扩展 webpack 的功能。作用更大,范围更广,可以打包优化、资源管理和注入环境变量等。

在 webpack 运行的生命周期中,会广播出许多事件,plugin 可以监听这些事件,在合适的实际,通过 webpack 提供的 api,改变输出结果。

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

module.exports = {
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};

plugins 和 loaders 比较:

  • loaders 负责的是处理源文件,如 css、jsx,一次只处理一个文件;
  • plugins 并不是直接操作单个文件,而是对整个构建过程起作用。

自定义配置 entry 和 output

下面开始自定义 webpack 配置啦,新建一个 build/webpack.config.js 文件。

然后把 打包命令改为:

  "scripts": {
    "build": "webpack --config build/webpack.config.js"
  },

1. entry (入口)

entry 可以是一个或多个。格式可以是字符串、数组和对象。

  • entry 为字符串:单个入口。输出一个打包后的文件,默认为 main.js。

build/webpack.config.js 输入:

module.exports = {
  mode: 'development', // 模式
  entry: './src/index.js',
}

npm run build,会发现生成了 dist 文件夹,里面有个 main.js,即打包后的结果。

  • entry 为数组:多个入口。输出一个打包后的文件。
entry: ['./src/index.js', './src/test.js'],

打包后,生成的 main.js 里面包含这两个js的内容。

  • entry 为对象:多个入口,有几个输入就有几个输出。输出文件的文件名称就是对象的key。
  entry: {
    output_index: './src/index.js',
    output_test: './src/test.js'
  },

打包后,dist里面有两个文件:

image.png

2. output (出口)

指明 webpack 打包后的资源输出到哪里,以及如何命名。

将 webpack.config.js 改为:

const path = require('path')

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: '[name].js', // 打包后资源的入口文件名
    path: path.resolve(__dirname, '../dist'), // 打包后资源存放的路径
  }
}

output 的其他参数:

  • output.clean (用于清理 dist 文件夹)

webpack 5.20版本以后可以用 output.clean 代替 clean-webpack-plugin,用于清除dist文件。

  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, '../dist'),
    clean: true,
  }

注释区

1. 关于 __dirname

__dirname: 当前文件所在文件夹的完整绝对路径。

在上面这个例子里,build/webpack.config.js 里面的 __dirname 是:

/Users/lilei/river/webpack-0222/01-init/build

2. 关于 path.resolve()

参数为个数不定的字符串,返回一个字符串。

原理:从后往前依次拼接,最终得到一个绝对路径字符串。

注意:以 / 开头为绝对路径,如果处理完所有参数后,还未得到绝对路径,则会加上当前工作目录的绝对路径。

再注意:当前文件的 __dirname 是: /Users/lilei/river/webpack-0222/01-init/build

而当前工作目录是:/Users/lilei/river/webpack-0222/01-init

规则:

  • / 开头的,不会拼接前面的路径,因为它本身就是绝对路径了;
  • ../ 开头的,会拼接前面的路径,把最后一节替换掉;
  • ./ 开头的,或者不带 / 的,会拼接前面的路径,跟着后面。
path.resolve('./cc'); // /Users/lilei/river/webpack-0222/01-init/cc
path.resolve('/aa/bb', 'cc'); // /aa/bb/cc
path.resolve('/aa/bb', './cc'); // /aa/bb/cc
path.resolve('/aa/bb', '../cc'); // /aa/cc
path.resolve('/aa/bb', '/cc'); // /cc
path.resolve('/root', './aa/bb', '../cc'); // /root/aa/cc
path.resolve('root', './aa/bb', '../cc'); // /Users/lilei/river/webpack-0222/01-init/root/aa/cc