# 换个角度学 Webpack

对 Webpack 可以说既熟悉也陌生,熟悉是因为工作中天天都在用到,陌生则是没怎么从头到尾去了解过,都是别人配好的,网上一些学习 Webpack 的文章都是上来就说怎么配怎么配,好吧,我脑子不够灵光记不住,于是乎换一种理解的方式来学习 Webpack。

# Webpack 干了什么?

关于什么是 Webpack,它有啥用,有什么优势劣势不在本文的讨论范围之内,有需求的同学请自行百度、谷歌。

那么 Webpack 的工作流程是什么呢?

image

可以看到上面这个简单的流程图,Webpack 进行打包工作的时候,先初始化配置,然后找到入口文件,然后去解析入口文件的依赖 Module 以及依赖的依赖等等,每个 Module 会根据不同的 Loader 进行转换,最后,根据 Entry 打包到不同的 Chunk 中去,最后输出文件。是不是很简单的一个流程,看懂了,配置也就好理解了。

那么有同学就要问了,Plugin 哪儿去了,好吧,Plugin 在可以在打包的不同阶段触发,然后执行插件的逻辑。

好了,现在我们清楚了流程,我们就开始配置了。

# 配置入口

首先,第一步,肯定就是入口文件的配置啦。

入口文件配置项 Entry,可以是字符串、数组或者对象。至于这三种配置什么区别相信大家见得也多了,这就不细说了。

这里要提的一点是入口配置的路径默认是以启动 Webpack 的目录为根目录,如果你想修改的话,可以配置 context 配置项。

那么配置完入口之后,下一步我们要做什么呢?没错我们要开始从入口模块解析依赖的模块了。

# 模块寻找

上面说到从入口模块,Webpack 要开始去解析依赖模块了,那么它去哪儿找呢?它自己默认的是有一套规则去寻找模块的,但是我们也可以根据自己的需求去修改规则,这就需要我们去配置 resolve 了,当然了,这个配置项不是必须的,可以根据需求来配置。

下面介绍一些,用的比较频繁的一些配置项。

resolve: {
    // alias 别名配置,它能够将导入语句里的关键字替换成你需要的路径
    alias: {
        // 比如我们就可以直接写 import Nav from 'component/Nav'
        'component': './app/component'
    },
    // 在导入的语句没有带后缀的时候,会尝试用这些后缀去匹配文件
    extensions: ['.ts', '.js']// 配置如何去寻找第三方模块,比如我们自己有一个组件库
    modules: ['./app/component', 'node_modules'],
}
1
2
3
4
5
6
7
8
9
10
11

现在 Webpack 能够准确的找到这些文件了,那么,现在我们就要开始对这些文件进行解析了。

# 模块解析

下面我们就去配置模块解析相关的配置项 Module了,在 Webpack 中,将一切的文件都视作模块,所以我们能够像引入 js 文件一样引入 css 或图片等资源。但是如果我们直接引入这些模块是会报错的,因为基础的 Webpack 是不支持转换这些模块的,我们需要 Loader。

那 Loader 是个啥?其实,大白话一点就是,Loader 是一个转换器,他可以帮助我们对模块的源代码进行转换,处理成我们需要的样子。

Module配置项中有一个 rules,它定义了一系列的规则,告诉 Webpack 遇到什么模块使用哪些 Loader 去进行加载转换。下面就以 js 代码使用 babel 进行转换为例。

module: {
    // rules 是个数组,是一系列的规则
    rules: [
        {
            test: '/\.js$/', // 正则表达式,去匹配要使用当前规则的模块
            use: ['babel-loader?cacheDirectory'], // 对匹配成功的模块使用 babel-loader 来进行转换,同时传入参数
        }
    ], 
}
1
2
3
4
5
6
7
8
9

可以看到我们对 js 代码转换配置了一条规则,在上面配置的每一条规则中还有些进行用到的配置,比如说 include 和 exclude,能够用来帮助缩小匹配的范围。

我们可以使用 Loader 来对 SCSS、JSX等等资源进行转换,这些都需要我们去配置 Loader。

# 输出配置

现在 Webpack 也已经解析完成了,我们需要去输出打包后的文件了,这时候我们就需要去配置 output 了。

output: {
    // 存放打包后文件的目录
    path: './build',
    // 打包后输出文件的名字,如果只有一个文件,你可以直接写死,如果不是的话就需要用到模板了,比如[name]、[hash] 、[id]等等
    filename: 'bundle.[hash].js'
}
1
2
3
4
5
6

其实到这里,Webpack 的基本配置流程就解决了,重要的是这个构建的流程思路。可能就会有人问了,插件在哪儿呢?插件在下面。

# 插件

用了这么多插件,其实对插件的配置不难,难的是插件提供的配置项,这个只有去插件的仓库学习了。

其实在配置构建的过程中,Webpack 不好解决的问题,你都可以去寻找插件的解决方案。

plugins: [
    // 每一项都是一个插件的实例
    new webpack.HotModuleReplacementPlugin(),
]
1
2
3
4

# 总结

这里只说了一些关于 Webpack 的基本配置和大概流程,希望大家理解了构建过程再去学习如何配置,会轻松很多,而不是一上来就学怎么配,反正我是记不住。

当然了还有一些,比如 devtool 的配置,有点多就不多说,大家可以大概了解一下,还有 devServer 的配置也比较多,以后可能会分享一下,谢谢阅读。