webpack知识体系 青训营笔记

52 阅读3分钟

1.webpack 是什么?

webpack 是一个现代 JavaScript 应用程序的静态模块打包器,当 webpack 处理应用程序时,会递归构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将这些模块打包成一个或多个 bundle

2.webpack 的核心概念

  • entry: 入口
  • output: 输出
  • loader: 模块转换器,用于把模块原内容按照需求转换成新内容
  • 插件(plugins): 扩展插件,在webpack构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要做的事情

3.初始化项目

新建一个文件夹,如: webpack-first (当然,你可以使用任意一个你喜欢的项目名)。推荐大家参考本文一步一步进行配置,不要总是在网上找什么最佳配置,你掌握了webpack之后,根据自己的需求配置出来的,就是最佳配置。

本篇文章对应的项目地址(编写本文时使用): github.com/YvetteLau/w…

使用 npm init -y 进行初始化(也可以使用 yarn)。

要使用 webpack,那么必然需要安装 webpackwebpack-cli:

npm install webpack webpack-cli -D
复制代码

鉴于前端技术变更迅速,祭出本篇文章基于 webpack 的版本号:

├── webpack@4.41.5 
└── webpack-cli@3.3.10 
复制代码

wepack V4.0.0 开始, webpack 是开箱即用的,在不引入任何配置文件的情况下就可以使用。

新建 src/index.js 文件,我们在文件中随便写点什么:

//index.js
class Animal {
    constructor(name) {
        this.name = name;
    }
    getName() {
        return this.name;
    }
}

const dog = new Animal('dog');
复制代码

使用 npx webpack --mode=development 进行构建,默认是 production 模式,我们为了更清楚得查看打包后的代码,使用 development 模式。

可以看到项目下多了个 dist 目录,里面有一个打包出来的文件 main.js

webpack 有默认的配置,如默认的入口文件是 ./src,默认打包到dist/main.js。更多的默认配置可以查看: node_modules/webpack/lib/WebpackOptionsDefaulter.js

查看 dist/main.js 文件,可以看到,src/index.js 并没有被转义为低版本的代码,这显然不是我们想要的。

{
    "./src/index.js":
        (function (module, exports) {

            eval("class Animal {\n    constructor(name) {\n        this.name = name;\n    }\n    getName() {\n        return this.name;\n    }\n}\n\nconst dog = new Animal('dog');\n\n//# sourceURL=webpack:///./src/index.js?");

        })
}
复制代码

4.将JS转义为低版本

前面我们说了 webpack 的四个核心概念,其中之一就是 loaderloader 用于对源代码进行转换,这正是我们现在所需要的。

将JS代码向低版本转换,我们需要使用 babel-loader

babel-loader

首先安装一下 babel-loader

npm install babel-loader -D
复制代码

此外,我们还需要配置 babel,为此我们安装一下以下依赖:

npm install @babel/core @babel/preset-env @babel/plugin-transform-runtime -D

npm install @babel/runtime @babel/runtime-corejs3
复制代码

对babel7配置不熟悉的小伙伴,可以阅读一下这篇文章: 不可错过的 Babel7 知识

新建 webpack.config.js,如下:

//webpack.config.js
module.exports = {
    module: {
        rules: [
            {
                test: /.jsx?$/,
                use: ['babel-loader'],
                exclude: /node_modules/ //排除 node_modules 目录
            }
        ]
    }
}
复制代码

建议给 loader 指定 include 或是 exclude,指定其中一个即可,因为 node_modules 目录通常不需要我们去编译,排除后,有效提升编译效率。

这里,我们可以在 .babelrc 中编写 babel 的配置,也可以在 webpack.config.js 中进行配置。

创建一个 .babelrc

配置如下:

{
    "presets": ["@babel/preset-env"],
    "plugins": [
        [
            "@babel/plugin-transform-runtime",
            {
                "corejs": 3
            }
        ]
    ]
}
复制代码

现在,我们重新执行 npx webpack --mode=development,查看 dist/main.js,会发现已经被编译成了低版本的JS代码。

在webpack中配置 babel

//webpack.config.js
module.exports = {
    // mode: 'development',
    module: {
        rules: [
            {
                test: /.jsx?$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ["@babel/preset-env"],
                        plugins: [
                            [
                                "@babel/plugin-transform-runtime",
                                {
                                    "corejs": 3
                                }
                            ]
                        ]
                    }
                },
                exclude: /node_modules/
            }
        ]
    }
}
复制代码

这里有几点需要说明:

  • loader 需要配置在 module.rules 中,rules 是一个数组。
  • loader 的格式为:
{
    test: /.jsx?$/,//匹配规则
    use: 'babel-loader'
}
复制代码

或者也可以像下面这样:

//适用于只有一个 loader 的情况
{
    test: /.jsx?$/,
    loader: 'babel-loader',
    options: {
        //...
    }
}
复制代码

test 字段是匹配规则,针对符合规则的文件进行处理。

use 字段有几种写法

  • 可以是一个字符串,例如上面的 use: 'babel-loader'
  • use 字段可以是一个数组,例如处理CSS文件是,use: ['style-loader', 'css-loader']
  • use 数组的每一项既可以是字符串也可以是一个对象,当我们需要在webpack 的配置文件中对 loader 进行配置,就需要将其编写为一个对象,并且在此对象的 options 字段中进行配置,如:
rules: [
    {
        test: /.jsx?$/,
        use: {
            loader: 'babel-loader',
            options: {
                presets: ["@babel/preset-env"]
            }
        },
        exclude: /node_modules/
    }
]
复制代码