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-react来处理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