引言:webpack以其强大且全面的功能在前端工程化构建的道路上大放异彩,有着丰富的社区生态,深受前端开发者的青睐,又正是因为其功能强大,接口丰富,扩展性强的特点,导致许多未接触过打包的新人(尤其是未经历过grunt,gulp阶段的)在入手webpack之初,看着如此繁多API及对应功能,有些头昏脑涨,本系列在此梳理关于webpack打包构建的脉络,很好的使用对应的打包技巧。
webpack是什么?
要使用webpack,首先要理解webpack是什么,根据官网首图介绍
就是将各种资源分门别类,整理成对应的js,图片,css资源,这就是webpack最核心的功能。因为前端页面就是通过样式,图片资源,JS脚本构成的,但是由于页面越来越复杂,资源引用,代码引用,样式引用等会变得越来越复杂,因此,webpack帮忙整理,最后生成有条理的资源,在提高开发效率的同时,也减少某些问题的发生。
webpack.config.js
webpack的基本配置文件,webpack有两种构建方式,一种是通过命令,另外一种是同构配置文件 webpack.config.js 通常情况下使用第二种,功能完善且易用性强**。**在构建时,webpack会自动识别该文件,并根据相关配置进行构建。
module.exports = {
entry: './src/index.js',
ouput: {
path: path.join(__dirname, './dist'),
filename: bundle.js
},
mode: 'production'
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
},
plugins: [
new xxxPlugin()
]
}
webpack主要知识点:
根据webpack.config.js配置文件,有主要以下几个知识点:
- entry
- output
- mode
- loader
- plugin
1.entry
构建的入口打包的源头
如官网图所示,作为主要文件的入口,在入口文件中会引用别的文件,而别的文件又引用许多别的文件,因此,入口就相当于一个线头,根据这个线头,把所有缠在这根线的其余线给解开并分类。
配置相关:
// 单入口打包构建
entry: './src/index.js', // 以单一字符串的形式
// 多入口打包构建
entry: {
index: './src/index.js',
test: './src/test.js'
} // 以map的 key-value 形式确定入口
2.output
webpack打包后的输出,既将整理并分类好的各种类型的内容文件存放的地方。
output: {
path: path.join(__dirname, './dist'),
filename: bundle.js | [name]_bundle.js,
// filename里面对应不同的打包方式
// 前者为单页应用,一般也只是单文件输出
// 后者为多页应用,根据entry对象的key作为 [name] 的占位符如 index_bundle.js, test_budle.js
}
3.mode
mode: 'production' | 'development' | 'none'
// 不同模式底下所集成的功能不同,
// 如:production 默认集成了uglifyjs,tree-shaking, hoisted-scope等功能
4.loader
由于webpack是在Node环境底下运行的,只能识别 JS 和 JSON 语言的内容
但是在前端里面还有类似CSS,图片资源,字体资源等相关内容,对于这些webpack不能识别的内容,需要将其转换为JS模块
loader就是这样的一个转换工具
loader本身其实就是一个函数,接受一个文件输入,将其转换为JS或者JSON输出
// loader 的本质
function loader(sourcefile) { // change the file to js code
const jscode = changeFile2JS(sourcefile);
return jscode;
}
loader配置,需要配置在module里面的rules,一种文件的匹配需要对应相关的loader
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader' // 如将ES6通过babel转换为ES5
},
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
// 用到多个loader用数组,loader的执行顺序由后往前,
// 即先执行css-loader转换css文件
// 而后使用style-loader 将其插入到 head 的 style 标签中 }
]
}
5.plugins
在整个webpack构建过程中,如构建开始,构建中,构建结束,生成构建产物等节点,webpack会有钩子抛出,而plugin就可以接入这个钩子,在对应的时间节点执行相应的功能,这样就相当于扩展了webpak的额外功能
将webpack整个构建过程比喻成一个制作 玩具的流水线,没有plugin的话,其最终可以制造出一个普普通通的玩具,没有美感,也没有太多的功能,但它的确是一个能玩的玩具
但是在制作的流水线上,有不同的工位,这些工位就好比plugin,如果说玩具注塑完成的地方有一个上颜色的工位,该工位可以让玩具具备各种各样的颜色,然后到最后完成的地方也有一个工位
打包装,这样玩具又有了漂亮的外壳包装。总而言之,这些plugin就是这些工位,在打包构建整个过程中,根据抛出的钩子,扩展出各种各样的功能。
plugins: [
new HtmlWebpackPlugin()
]
还可以根据自己的需要编写对应的plugin
通过webpack打包一个简单项目
了解并知悉了以上5个功能对应的知识点,其实就可以用webpack构建一个简单的项目了。
安装webpack
mkdir webpack && cd webpack // 新建一个webpack目录
npm init -y
// 生成一个package.json 文件,初始化项目
npm i webpack webpack-cli -D // 安装webpack 及 webpack 脚手架
新建src文件夹及添加index.js文件,新建webpack.config.js配置文件
得到如下项目目录
首先在package.json里面添加build打包命令
"script" : {
"build": "webpack"
}
配置webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, './dist'),
filename: bundle.js
},
mode: 'production',
}
执行构建
最简单的一个打包,甚至不将 es6 转换为 es5
index.js文件如下:
export function helloworld() {
const map = {
hello: 'hello',
world: 'world'
};
const { hello, world } = map;
return `${hello} ${world}`;
}
document.write(helloworld());
这里故意用了 es6 的语法,执行 npm run build 看下打包出来之后的产物是啥
可以看到通过配置output输出到了dist文件夹,同时文件名称为bundle.js
bundle.js
(()=>{"use strict";document.write(function(){const{hello:l,world:o}={hello:"hello",world:"world"};return`${l} ${o}`}())})();
可以看到这里的代码被压缩了(这个就是mode为production集成的功能),同时还是 es6 的语法,并没有作任何改动;
babel-loader
前文提到loader的作用,就是将各种文件转化为JS文件,同样的由于es6 并没有完全被兼容,所以这里要把 js 文件通过babel 把 es6 转换为 es5。
babel的具体功能可翻阅官网文档
那么需要用到以下几个包
@babel/core @babel/preset-env @babel-loader
npm i @babel/core @babel/preset-env @babel-loader -D
同时还需要创建babel配置,用官方推荐的 .babelrc
.babelrc 配置
{
"presets": [ ["@babel/preset-env"], // 将 es6 转换为 es5
// "@babel/preset-react" 如果要将react转换的话,
// 则需要这个,同理,其余的要转换,也要安装对应的包 ],
plugins: []
}
此时执行npm run build
将会得到dist文件,其中的bundle.js文件
(()=>{"use strict";document.write(("world","".concat("hello"," ").concat("world")))})();
显然看到这里的转换跟之前不太一致,这里已经转换为通用的es5了
至此,一个最简单的webpack打包,便已完成。
总结
webpack功能虽然强大繁多,但是抓清其主要打包脉络,使用起来也不会说太复杂。
熟悉主要几个概念:
- entry
- output
- mode
- loader
- plugin
并通过webpack.config.js配置文件进行一个简单的项目打包,了解这几个概念是如何起作用的。
但要想构建一个更加现代化的前端项目,光了解这些内容,还是不够的,请期待下一篇:
webpack打包系列-2.react项目打包及图片样式资源引入