Webpack配置,让你的代码飞得更高!(小鸟不一定会唱歌)
开篇
Webpack
是一种用于构建JavaScript
应用程序的静态模块打包工具。它将应用程序的各个模块打包成一个或多个文件,以便于在浏览器中加载。Webpack
提供了一个灵活的配置系统,让开发人员可以根据自己的需求来定制打包过程。
下面是Webpack
配置的部分指南,让我们开始去了解了解吧。
安装Webpack
首先,我们需要安装Webpack
。Webpack
可以通过npm
来安装,执行以下命令即可:
npm install webpack webpack-cli --save-dev
创建Webpack配置文件
Webpack
的配置文件通常被命名为webpack.config.js
,位于项目的根目录下。我们可以通过编写JavaScript
代码来配置Webpack打包过程。
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
在此配置中,我们通过module.exports
导出了一个对象,其中包含了两个属性:
entry
: 表示Webpack应该从哪个文件开始打包
。在此配置中,Webpack从名为index.js
的文件开始打包。output
: 表示打包好的文件应该输出
到哪里。在此配置中,打包好的文件将输出到dist目录
下,文件名为bundle.js。
配置Loader
Loader是Webpack的核心概念之一。它允许Webpack在打包过程中对各种类型的文件进行转换处理。通过使用不同的Loader,我们可以让Webpack打包处理不同种类的文件,如CSS、图片、字体等。
下面介绍一下Loader的常见配置选项:
test
: 用于匹配需要 Loader 转换的文件。可以是正则表达式,也可以是一个文件路径。比如,test: /.js$/
表示匹配所有的.js
文件。exclude
: 这个表示排除不需要匹配的文件夹或文件。如,exclude: /node_modules/
表示忽略node_modules
文件夹下的所有内容。include
: 这个表示只对需要匹配的文件夹或文件进行匹配。如,include: /src/
只匹配src
文件夹下的内容。use
: 用于指定 Loader 名称,可以是一个字符串或数组。它可以是预设的 Loader 名称,也可以是自定义的 Loader 名称。当需要使用多个 Loader 时,可以使用数组进行列表。options
: 这个用于指定 Loader 的参数,通常用于传递额外的选项。
下面是一个例子,使用css-loader
和style-loader
处理CSS文件:
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
}
]
}
]
}
};
在此配置中,我们使用了两个Loader来处理CSS文件。首先,Webpack使用css-loader
将CSS文件
转换为JavaScript模块
,然后使用style-loader
将该模块作为样式添加到HTML文件中。
配置Babel
Babel
是一种JavaScript编译器,它可以将最新版本的JavaScript转换为向后兼容的代码,以便于在老旧的浏览器上运行。我们可以使用Webpack
的babel-loader
来配置Babel转换过程。
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
};
在此配置中,我们使用babel-loader
来处理所有的.js文件。babel-loader使用options选项来配置Babel的preset。在此配置中,我们使用了@babel/preset-env
,它可以根据目标浏览器和项目中使用的JavaScript特性来自动选择转换规则。
配置Plugin
Plugin
是Webpack的另一个核心概念。它们可以用于执行各种任务,如优化打包过程、引入全局变量、对输出文件进行处理
等。
下面是一个例子,使用HtmlWebpackPlugin
插件自动生成HTML文件:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
};
在此配置中,我们使用HtmlWebpackPlugin
插件来生成一个HTML文件。该插件将使用index.html文件中的模板进行生成。
处理环境变量
在开发和生产环境下,我们可能需要使用不同的配置参数。Webpack提供了处理环境变量的机制,以便于灵活配置打包过程。
下面是一个例子,使用webpack-merge
插件来合并不同环境下的配置:
const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.config.js');
module.exports = (env, argv) => {
if (argv.mode === 'development') {
return merge(commonConfig, {
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
}
});
}
if (argv.mode === 'production') {
return merge(commonConfig, {
devtool: 'source-map'
});
}
};
在此配置中,我们首先通过require
导入了webpack-merge
插件和一个名为webpack.common.config.js
的公共配置文件。然后,我们通过module.exports
导出一个函数,该函数将根据不同的环境变量返回不同的配置。
配置TypeScript
TypeScript是一种JavaScript的超集,它添加了类型检查和其他语言特性,使得代码更加稳健可靠。我们可以使用Webpack的ts-loader
来配置TypeScript转换过程。
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /.ts$/,
exclude: /(node_modules)/,
use: {
loader: 'ts-loader'
}
}
]
}
};
在此配置中,我们使用了ts-loader
来处理所有的.ts
文件。ts-loader会根据tsconfig.json
中的配置来转换TypeScript代码。
配置React
React是一种流行的JavaScript库,可以用于构建复杂的用户界面。我们可以使用Webpack的babel-loader
来处理React代码,并配置React的转换规则。
module.exports = {
entry: './src/index.jsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
}
]
}
};
在此配置中,我们使用了babel-loader
来处理所有的.js
和.jsx
文件。我们使用了@babel/preset-env
来处理JavaScript代码,使用了@babel/preset-reac
t来处理React代码。
配置CSS
Webpack可以处理各种类型的静态资源,包括CSS文件。我们可以使用Webpack的css-loader
和style-loader
来配置CSS的转换和添加。
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
在此配置中,我们使用了style-loader
和css-loader
来处理CSS文件。css-loader
会将CSS转换为JavaScript模块,style-loader
会将该模块作为样式添加到HTML文件中。
配置图片
Webpack可以通过file-loader
和url-loader
将图像转换为模块,并插入到JavaScript代码或样式表中。
module.exports = {
// ...
module: {
rules: [
{
test: /.(png|jpe?g|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
name: '[name].[hash].[ext]',
outputPath: 'images'
},
},
],
},
],
},
};
在此配置中,我们使用了url-loader
,它可以将小的图像文件
转换为base64 URL
,并将大的图像
文件作为物理文件复制到输出目录
。在此配置中,我们设置了limit选项
,如果文件大小小于8192B
,则图像文件将转换为base64
,否则文件将被复制到输出目录,文件名由原始名称
、哈希
和扩展名
构成,并且存储在images
目录下。
配置字体
Webpack可以通过file-loader
和url-loader
将字体转换为模块,并插入到JavaScript代码或样式表中。
module.exports = {
// ...
module: {
rules: [
{
test: /.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash][ext]'
}
},
],
},
};
在此配置中,我们使用了asset/resource生成器类型
,它可以将字体文件复制到输出目录,并将文件名由原始名称、哈希和扩展名
构成,并且存储在fonts
目录下。
配置代码分割
Webpack可以将代码分割成多个块,以便按需加载和减少初始加载时间。
module.exports = {
// ...
optimization: {
splitChunks: {
chunks: 'all',
minSize: 10000,
maxSize: 250000,
cacheGroups: {
defaultVendors: {
test: /[\/]node_modules[\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};
在此配置中,我们使用了splitChunks
选项来配置代码分割。我们设置了chunks
选项为’all’
,可以将代码分割为同步和异步
块。我们还设置了minSize
和maxSize
选项,指定了块的最小和最大大小。我们定义了两个缓存组
,一个是defaultVendors缓存组
,用于将来自node_modules目录的代码提取到单独的块中
,一个是default缓存组
,用于将多个块共享的模块提取到单独的块中
。
配置无需打包的库
有些库是我们不需要打包的,因为它们的大小很大,并且它们不会经常更改。我们可以使用Webpack的externals
选项来忽略这些库,并从CDN或其他外部源加载它们。
module.exports = {
// ...
externals: {
jquery: 'jQuery'
},
};
在此配置中,我们使用了externals
选项,将jquery库从打包中排除,并将它视为全局变量’jQuery’。这意味着我们不需要在Webpack打包中包含jquery,因为我们将在HTML文件中使用CDN或其他外部源加载它。
配置多页面应用
除了单页面应用之外,Webpack也可以用于构建多页面应用
。我们可以使用Webpack的entry
选项来指定每个页面的入口文件,并使用HtmlWebpackPlugin
生成每个页面所需的HTML文件。
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
home: './src/home.js',
about: './src/about.js',
contact: './src/contact.js',
},
plugins: [
new HtmlWebpackPlugin({
filename: 'home.html',
template: './src/home.html',
chunks: ['home']
}),
new HtmlWebpackPlugin({
filename: 'about.html',
template: './src/about.html',
chunks: ['about']
}),
new HtmlWebpackPlugin({
filename: 'contact.html',
template: './src/contact.html',
chunks: ['contact']
}),
],
};
在这个示例中,我们使用Webpack的entry选项指定了三个页面的入口文件。我们还使用HtmlWebpackPlugin插件
生成了每个页面所需的HTML文件,并指定了与当前页面相关的块,以确保Webpack只添加正确的JavaScript代码。
配置热模块替换
Webpack可以使用Hot Module Replacement(HMR)
来在运行时更新模块而不需要重新加载整个页面。我们可以通过Webpack Dev Server和HotModuleReplacementPlugin
来启用热模块替换。
// webpack.config.js
const webpack = require('webpack');
module.exports = {
// ...
devServer: {
contentBase: './dist',
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
};
在这个示例中,我们使用Webpack Dev Server的contentBase
选项指定了应用程序的基本目录,并启用了hot选项
以启用HMR
。我们还使用webpack的HotModuleReplacementPlugin插件
来启用模块热替换。
配置代码格式化
我们可以使用Prettier
和ESLint
等工具来格式化我们的代码。Webpack可以使用loader
和plugin
为我们的代码自动格式化。
// webpack.config.js
module.exports = {
// ...
module: {
rules: [
{
// Use Prettier to format JavaScript code
enforce: 'pre',
test: /.js$/,
loader: 'prettier-loader',
options: {
// Prettier options
}
},
{
// Use ESLint to lint and format JavaScript code
enforce: 'pre',
test: /.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
// ESLint options
}
},
],
},
plugins: [
// Use Prettier to format HTML and CSS code
new PrettierPlugin({
// Prettier options
}),
],
};
在这个示例中,我们使用Prettier
和ESLint
来格式化和检查我们的代码。我们定义了两个规则,一个使用prettier-loader
来使用Prettier
格式化我们的JavaScript代码,并使用eslint-loader
来使用ESLint检查和格式化代码
。我们还使用PrettierPlugin插件
来格式化我们的HTML和CSS
代码。这些工具都需要安装并正确配置,才能在Webpack中使用。
webpack性能优化
Webpack在打包过程中可能会产生大量的中间文件,导致打包速度变慢。为了优化Webpack的性能,我们需要进行一些额外的配置。
下面是一些优化Webpack性能的方法:
- 使用
更高版本的Webpack和相关工具
,以获得更好的性能表现。- 通过
Tree Shaking
的方式精简打包后的文件,去掉未使用的代码和模块。- 用
uglifyjs-webpack-plugin
或terser-webpack-plugin
压缩打包后的文件,以减小文件大小。- 使用
cache-loader
或hard-source-webpack-plugin
将中间文件缓存到内存或者硬盘中,以加快打包速度。- 在开发环境下使用
webpack-dev-server
或webpack-dev-middleware
提高打包性能。这两个工具允许我们将文件打包到内存中,以避免多次读写磁盘文件。
分包
在Webpack中,可以使用SplitChunksPlugin
进行分包,将公共模块提取出来单独生成一个文件,避免每个页面都加载相同的代码。具体可以按照以下步骤进行配置:
- 在
optimization
中添加splitChunks
选项,用于配置分包规则。
optimization: {
splitChunks: {
chunks: 'all', // 所有类型的chunks都被考虑
minSize: 30000, // 生成的Chunk最小的大小
minChunks: 1, // 被多少模块共享
maxAsyncRequests: 5, // 按需加载的最大并行请求数
maxInitialRequests: 3, // 初始加载的最大并行请求数
name: true, // 生成的Chunk名
cacheGroups: {
vendors: { // 第三方资源
test: /[\/]node_modules[\/]/,
priority: -10,
filename: 'vendors.js'
},
default: { // 其他公共模块
minChunks: 2,
priority: -20,
reuseExistingChunk: true, // 公共模块之间是否可以复用
filename: 'common.js'
}
}
}
}
chunks
指定需要提取的Chunk类型,minSize
指定生成的Chunk最小大小,minChunks
指定被多少模块共享才可以被提取,cacheGroups
用于配置不同类型的Chunk的提取规则,将公共模块提取出来单独成为一个文件。
- 在
output
中添加filename
选项,用于指定生成的文件名。
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
}
[name]
会被替换为Chunk的名称。
完成以上配置后,再次重新构建时,Webpack会根据分包规则将公共模块提取出来单独生成文件。
总结
别让你的代码像一只笨重的企鹅,赶快配置Webpack,让它像一只轻盈的小鸟,飞向更高的层次!(小鸟不一定会唱歌)
转载自:https://juejin.cn/post/7240877252719968311