当我们安装好webpack
之后,就可以使用webpack
命令了,比如要将一个main.js
文件打包成一个bundle.js
文件,可以使用如下命令:
webpack main.js bundle.js
一般在实际的项目开发中,要把这些命令写到一个webpack.config.js
的文件中。上面打包操作可以做如下配置:
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
}
};
在上面的配置文件中,我们配置了项目的入口(entry
)和出口(output
),在该项目的关系图中,entry
字段指定了入口文件,即把main.js
作为起点。output
字段是指定了输出位置,即指定webpack
把整理后的资源放在哪里。
webpack
主要有4个核心概念:
入口(entry
):项目入口,也是webpack
所有依赖关系图的起点。
出口(output
):指定webpack
打包应用程序的目录。
加载器(loader
):加载需要处理的模块,对模块进行转换处理。
插件(plugins
):定义项目要用到的插件。
在前面的内容中,我们已经了解到了,webpack
是一个模块打包工具,需要处理具有依赖关系的各个模块,这些模块会构成一个依赖关系图(dependency graph)。webpack
的入口就是这张关系图的起点,指的是入口文件。webpack
出口指的是需要把这张关系图导出到哪个文件中,即导出文件。
(1)入口(entry)
entry
字段指定了入口文件,也可以理解为当前项目启动时运行的第一个文件,语法为:
entry: string | object | Arrary
entry
字段支持多种类型,值可以是字符串、对象、数组。简单来理解,就是entry
可以指定一个文件入口,也可以指定多文件入口。我们举例来说明entry
的用法:
单文件入口示例
// 使用key-value方式
module.exports = {
entry: 'path/to/my/entry/main.js'
};
// 或者使用对象方式
module.exports = {
entry: {
main: 'path/to/my/entry/main.js'
}
};
// entry也可以使用数组指定多个入口文件路径,输出时会合并输出
module.exports = {
mode: 'development',
entry: ['./src/app.js', './src/home.js'],
output: {
filename: 'array.js'
}
};
多文件入口
// entry配置3个独立的入口文件,会打包成3个对应的bundle
module.exports = {
entry: {
home: 'path/to/my/entry/home.js',
search: 'path/to/my/entry/search.js',
list: 'path/to/my/entry/list.js'
}
};
(2)出口(output)
output
字段是指定entry
对应文件编译打包后的输出位置,也可以理解为指定webpack
把整理好的资源放到哪里。output
字段常用的属性有:
path
:指定打包完成的文件存放的路径;filename
:指定打包完成的文件的文件名称;publicPath
:指定一个在浏览器中被引用的URL地址;如果不指定path
参数,将默认将打包文件输出到webpack.config.js
同级目录下;如果不指定output
,打包文件会默认输出到dis/main.js
,即output
字段的path
属性默认是dis
,filename
属性默认是main
。
一个webpack
的配置可以包含多个entry
,但是只能有一个output
。对于不同的entry可以通过output.filename
占位符语法来区分,例如:
module.exports = {
entry: {
home: 'path/to/my/entry/home.js',
search: 'path/to/my/entry/search.js',
list: 'path/to/my/entry/list.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
};
在上面的配置中,output.filename
指定的[name]
就是一个占位符,对应的是entry
中的key
(home
、search
、list
),最终输出的结果是:
path/to/my/entry/home.js → dist/home.js
path/to/my/entry/search.js → dist/search.js
path/to/my/entry/list.js → dist/list.js
目前webpack
支持的占位符有:
占位符 | 含义 |
---|---|
[hash] |
模块标识符的hash |
[chunkhash] |
chunk 内容的hash |
[name] |
模块的名称 |
[id] |
模块标识符 |
[query] |
模块的query ,例如,文件名 ? 后面的字符串 |
[function] |
一个 return 出一个 string 作为 filename 的函数 |
loader
是解析处理器,大家都知道,webpack
的任务就是把具有依赖关系的各个文件进行整合并打包,这些文件的类型有很多,比如.html
、.css
、.js
、.scss
、.jpg
等等。但是webpack
只认识JavaScript
文件,那如何识别其他文件呢?loader
就解决了这个问题。比如,很多浏览器不支持ES6
语法,webpack
可以通过loader
配置,将ES6
语法转化为ES5
的语法,还可以将图片转化为base64
的dataURL
,还可以通过loader
直接在JavaScript
文件中使用import
引入css
和html
。
loader
在webpack
构建文件的过程中起着至关重要的作用,实现可以通过loader
识别出要对哪些文件进行预处理,然后loader
转换这些需要预处理的文件,并添加到bundle
(构建后的模块)中。在React
框架开发时,经常会用到JSX
这种扩展语言来编写DOM
,目前几乎所有的浏览器都不支持JSX
格式,那么loader
就可以在使用JSX
之前做一些预处理操作,将其转化成JavaScript
语言,示例如下:
module.exports = {
entry: {
app: './app.js'
}
output: {
filename: 'bundle.js',
path: './dist'
}
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: 'babel-loader'
},
{
test: /\.css$/,
use: 'css-loader'
}
]
}
}
在上面的例子中,test
字段表示要对哪些类型的文件进行构建,use
字段表示要用哪些模块对该类型的文件进行构建。在test
项中使用/\.css$/
这种正则表达式来匹配需要处理的模块文件,即匹配以.css
为后缀的文件。
在配置loader
之前,use
中的模块是需要安装的,命令如下:
npm install --save-dev babel-loader
npm install --save-dev css-loader
提示:
在
webpack
的早期版本中,loader
的写法是:module.exports = { ...... module: { loaders: [ { test: /\.(js|jsx)/, loader: 'babel-loader' }, ...... ] } }
webpack
最新版本中已经废弃了loaders
、loader
的写法,改成了rules
、use
。
plugin
在webpack
起着重要的作用,通过plugin
可以解决loader
解决不了的问题,以此来丰富webpack
的功能。webpack
本身就是有很多插件组成的,所以内置了很多插件。除了内置插件,我们也可以通过NPM
包的方式来使用插件,比如现在需要安装一个html-webpack-plugin
的插件,先执行安装命令:
npm install --save-dev html-webpack-plugin
然后在webpack.config.js
文件中配置plugins
:
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './app.js'
},
output: {
filename: 'bundle.js',
path: './dist'
},
module: {
rules: [
{
test: /\.(js|jsx)/,
use: 'babel-loader'
},
{
test: /\.css$/,
use: 'css-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin()
]
}
上面的示例中,plugins
参数为一个数组,可以传入多个plugin
,另外需要注意plugin
是可以带参数的,所以plugins
属性传入的必修为new
实例。