webpack具有相当多的配置项,常见且基础的配置项如entry,output,mode,plugins等等,这篇博客是笔者关于这些基础配置的知识整理。
1. entry
起点或是应用程序的起点入口。从这个起点开始,应用程序启动执行。如果传递一个数组,那么数组的每一项都会执行。
module.exports = {
// entry: './src/js/hello.js',
entry: {
main: './src/js/hello.js'
}
}
2. output
output 位于对象最顶级键(key),包括了一组选项,指示 webpack 如何去输出、以及在哪里输出你的「bundle、asset 和其他你所打包或使用 webpack 载入的任何内容」。
output具有相当多的配置项,这里仅仅介绍filename,path等一些基础配置,更多详情可以前往webpack文档查看
2.1 output.path
output 目录对应一个绝对路径。
module.exports = {
//...
output: {
path: path.resolve(__dirname, 'dist/assets')
}
};
打包后的文件将会输出到指定的文件夹下面。
2.2 output.filename
此选项决定了每个输出 bundle 的名称。这些 bundle 将写入到 output.path 选项指定的目录下。
对于单个入口起点,filename 会是一个静态名称。
//webpack.config.js
module.exports = {
//...
output: {
filename: 'bundle.js'
}
};
然而,当通过多个入口起点(entry point)、代码拆分(code splitting)或各种插件(plugin)创建多个 bundle,应该使用placeholder为每一个bundle提供一个唯一的名称,如:
module.exports = {
//...
output: {
filename: '[name].bundle.js'
}
};
3. module
module选项决定了如何处理项目中不同类型的模块。
module具有两个配置项,noParse
和rules
3.1 module.noParse
防止 webpack 解析那些任何与给定正则表达式相匹配的文件。忽略的文件中不应该含有 import, require, define 的调用,或任何其他导入机制。忽略大型的 library 可以提高构建性能。
module.exports = {
//...
module: {
noParse: /jquery|lodash/,
}
};
3.2 module.rules
创建模块时,匹配请求的规则数组。这些规则能够修改模块的创建方式。这些规则能够对模块(module)应用 loader,或者修改解析器(parser)。
Webpack 支持使用 loader 对文件进行预处理。你可以构建包括 JavaScript 在内的任何静态资源。并且可以使用 Node.js 轻松编写自己的 loader。
而module.rules
中的每一个rule都能分为三部分,条件(condition),结果(result)和嵌套规则(nested rule)。
条件就是我们以之作为判断文件是否使用该rule,一般我们是有正则匹配一类文件;结果就是当文件满足该rule时应用的loader或者Parser选项
大多数情况下,我们只需要设置rule的条件和结果即可。
rules: [{
test:/\.(png|jpg|gif)$/,
use:{
loader: 'url-loader',
options: {
name: '[name].[ext]',//placeholder占位符
outputPath:'image/',
limit: 2048 //2kb
}
}
},{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
}]
这里我们使用了Rule.test
,Rule.test 是 Rule.resource.test 的简写。如果你提供了一个 Rule.test 选项,就不能再提供 Rule.resource。Rule.test后我们使用了一个正则表达式,当一个文件的文件名满足该正则表达式的时候,就应用Rule.use
中的loaders进行解析。
Rule.use
可以是一个应用于模块的 UseEntries 数组。每个入口(entry)指定使用一个 loader。当Rule.use中有多个loader时,目标文件是由下而上,由右到左进行解析的,所以Rule.use中的loader顺序也很重要。
关于loader的配置项可以在相关loader的文档中进行查看。
4. plugins
plugins 选项用于以各种方式自定义 webpack 构建过程。
plugins是一组 webpack 插件。例如,DefinePlugin 允许你创建可在编译时配置的全局常量。这对需要再开发环境构建和生产环境构建之间产生不同行为来说非常有用。
在我们的项目实现过程中,适当地使用插件可以提高我们的编程效率,极大地提升编程体验。
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: './src/html/index.html'
}),new CleanWebpackPlugin(['dist'])
],
...
}
这里的httpwebpackplugin会在打包结束后,自动生成一个html文件,并把打包生成的js自动引入到这个html文件中,而CleanWebpackPlugin则可以删除掉打包前dist目录下的所有文件。
5. mode
提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。
mode可以设置三种值,分别是development,production,none
,如果没有设置,webpack 会给 mode 的默认值设置为 production。
当设置了mode值之后,webpack会自动为配置文件增加一些配置,比如在development
开发者:
devtool: 'eval',
cache: true,
performance: {
hints: false
},
output: {
pathinfo: true
},
...//这仅仅是添加的一部分配置
6. devtool
此选项控制是否生成,以及如何生成 source map。
使用 SourceMapDevToolPlugin 进行更细粒度的配置。查看 source-map-loader 来处理已有的 source map。
什么是source map?
source map是一种映射关系,如果不启用source map,那么当js文件出错时,控制台会提示我们打包后的js文件的出错位置,这并不便于我们的bug修复,而启用source map之后,控制台可以告诉我们打包之前的js文件中的出错位置。
devtool启用source-map之后,由于需要生成bundle和源文件的映射关系,会在一定程度下拉低webpack的性能。
devtool有多个取值,详情可见webpack文档
在development环境下,我们推荐:
devtool: 'cheap-module-eval-source-map'
在production环境下,我们推荐:
devtool: 'cheap-module-source-map'
但是针对不同的打包情况情况,我们可以选用更适合的devtool值。
7. devServer
webpack-dev-server能够帮助我们凯苏开发应用程序。
webpack-dev-server可以帮我们启动一个http服务器,并且可以实时监测我们是否改变了源文件,当打包的源文件发生改变时,重新打包并刷新。
在使用此配置之前,应该先安装webpack-dev-server:
npm install webpack-dev-server
devServer: {
contentBase: path.resolve(__dirname,'dist'),
open: true,
port: 8090
},
**contentBase: ** 告诉服务器从哪个目录中提供内容。只有在你想要提供静态文件时才需要。devServer.publicPath 将用于确定应该从哪里提供 bundle,并且此选项优先。
open: 告诉 dev-server 在 server 启动后打开浏览器。默认禁用。
port: 指定要监听请求的端口号
webpack-dev-server会将dist目录中的文件放入内存,以提高打包速度。
devServer已经是一个相当成熟的webpack开发服务器,具有相当多的配置信息,更多详情可以查看webpack文档。
8. Hot Module Replacement 热模块更新
当webpack-dev-server发现打包源文件发生改变之后,会重新发起一个网络请求,也就是浏览器将刷新。如果我们想要更改一个组件的样式,并且浏览器不刷新,仅仅是更新该组件的样式,这时候我们就可以使用热模块更新。
module.exports = {
...
devServer: {
contentBase: path.resolve(__dirname,'dist'),
open: true,
port: 8090,
hot:true,
hotOnly: true
},
plugins: [
new HtmlWebpackPlugin({
template: './src/html/index.html'
}),new CleanWebpackPlugin(['dist']),
new webpack.HotModuleReplacementPlugin()
],
...
}
9. 使用Bebal处理ES6语法
目前浏览器中,并不是所用的浏览器都支持ES6语法,这些浏览器不能识别打包后文件中ES6语法,可能会和我们的预期产生偏差。
Bebal可以将ES6的语法装换成浏览器兼容的代码。
npm install --save-dev babel-loader @babel/core
{
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
}
npm install @babel/preset-env --save-dev
@babel/preset-env b
//新建一个babel.config.json
{
"presets": ["@babel/preset-env"]
}
以上就完成了ES6的语法翻译,但是一些es6的对象在一些老版本的浏览器中依然不能识别,这时候,我们还需要polyfill
对es6对象进行说明:
npm install @babel/polyfill -D
然后我们将其引入到业务代码的最顶部:
//index.js
import "@babel/polyfill";
...
...
这样打包后的文件可能远远大于不使用babel打包生成的文件,因为polyfill将所有es6对象都进行了引入,但是如果我们只用到了一部分,这时候我们可以更改babel-loader的options:
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [['@babel/preset-env',{
useBuiltIns: 'usage'//根据需求添加相关代码
}]]
}
}
},
...]
}