Webpack基础学习-Day01
1.1 webpack 是什么
webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler)。
在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/…)都会作为模块处理。
它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。
1.2 webpack 核心概念
1.2.1 Entry
入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图。
在 Webpack 中,entry
属性指定了 Webpack 用来构建其内部依赖图的起点或入口点。换句话说,entry
告诉 Webpack 从哪里开始打包代码。
entry
属性的用法
entry
属性的值可以是以下几种类型:
- 字符串:单个入口文件。
- 数组:多个入口文件,这些文件的内容会被打包到一个 bundle 中。
- 对象:多个入口点,每个入口点会生成一个独立的 bundle。
1. 字符串类型的 entry
这是最简单的用法,指定一个单一的入口文件:
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
在这种情况下,Webpack 从 ./src/index.js
开始构建依赖图,并将所有模块打包到 bundle.js
文件中。
2. 数组类型的 entry
如果你有多个文件需要作为入口,但希望将它们打包到一个 bundle 中,可以使用数组:
module.exports = {
entry: ['./src/index.js', './src/anotherModule.js'],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
这种情况下,index.js
和 anotherModule.js
会被打包到同一个 bundle.js
文件中。
3. 对象类型的 entry
对象类型的 entry
允许你定义多个独立的入口点,每个入口点会生成一个独立的 bundle:
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
在这种情况下,会生成两个独立的 bundle 文件:app.bundle.js
和 admin.bundle.js
。[name]
是一个占位符,会被 entry
对象的键替换。
高级用法
动态入口
可以通过函数返回一个对象来动态生成入口点:
module.exports = {
entry: () => {
const entries = {
main: './src/main.js',
};
if (process.env.NODE_ENV === 'development') {
entries.dev = './src/dev.js';
}
return entries;
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
这种方式允许根据环境或其他条件动态配置入口点。
使用多个入口和 SplitChunks 插件
通过配合 SplitChunksPlugin
,可以将共享代码提取到一个独立的 chunk 中:
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
splitChunks: {
chunks: 'all',
},
},
};
这种配置会将 app.js
和 admin.js
中的共享模块提取到一个公共的 bundle 中,从而减少重复代码。
配置示例
以下是一个更完整的 Webpack 配置示例,展示了不同类型的 entry
配置和一些常见的插件配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].[contenthash].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html',
chunks: ['app'], // 仅包含 app chunk
}),
new HtmlWebpackPlugin({
template: './src/admin-template.html',
filename: 'admin.html',
chunks: ['admin'], // 仅包含 admin chunk
}),
],
optimization: {
splitChunks: {
chunks: 'all',
},
},
};
总结
entry
属性是 Webpack 配置中的一个重要部分,它定义了 Webpack 构建的入口点。通过灵活使用字符串、数组和对象类型的 entry
,你可以实现不同的构建策略和优化代码拆分。结合 Webpack 的其他特性(如插件和优化选项),可以构建高效、可维护的前端项目。
1.2.2 Output
输出(Output)指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名。
output
属性是 Webpack 配置中的一个关键部分,它定义了打包后输出文件的相关设置。通过配置 output
,你可以指定打包文件的名称、路径、公共路径等。
基本配置
1. filename
filename
用于指定输出文件的名称。可以使用占位符来生成动态文件名。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js', // 输出文件名
path: path.resolve(__dirname, 'dist'), // 输出路径
},
};
常用的占位符包括:
[name]
: 入口点名称[id]
: chunk ID[hash]
: 编译时的唯一 hash[chunkhash]
: chunk 的 hash[contenthash]
: 文件内容的 hash
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].[contenthash].js', // 动态生成文件名
path: path.resolve(__dirname, 'dist'),
},
};
2. path
path
用于指定输出目录的绝对路径。通常使用 Node.js 的 path
模块来生成绝对路径。
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'), // 使用绝对路径
},
};
3. publicPath
publicPath
用于指定输出解析文件的公共 URL 地址。通常用于配置 CDN 地址或开发服务器地址。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/', // 公共路径,通常用于配置 CDN 地址
},
};
高级配置
1. chunkFilename
chunkFilename
用于指定按需加载的 chunk 文件的名称模板。类似于 filename
,可以使用占位符。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
chunkFilename: '[name].[contenthash].js', // 按需加载的 chunk 文件名
},
};
2. assetModuleFilename
assetModuleFilename
用于指定通过资源模块(如图像、字体等)处理的文件的输出文件名模板。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: 'assets/[name].[hash][ext]', // 资源模块文件名
},
};
3. library
和 libraryTarget
library
和 libraryTarget
用于将你的 bundle 输出为一个库。
library
指定库的名称。libraryTarget
指定导出库的方式(如var
,umd
,commonjs2
等)。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
library: 'MyLibrary', // 库名称
libraryTarget: 'umd', // 输出库的方式
},
};
常见示例
示例 1:简单的单入口点配置
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
示例 2:多入口点配置
const path = require('path');
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
},
};
示例 3:配置公共路径
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'https://cdn.example.com/assets/', // 使用 CDN 地址
},
};
示例 4:配置资源模块输出
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: 'images/[name].[hash][ext]', // 资源模块文件名
},
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
};
详细解释
filename
:指定输出文件的名称,可以使用占位符动态生成文件名。path
:指定输出目录的绝对路径,通常使用 Node.js 的path.resolve
方法。publicPath
:指定公共路径,通常用于配置 CDN 地址或开发服务器地址。chunkFilename
:指定按需加载的 chunk 文件的名称模板。assetModuleFilename
:指定资源模块处理的文件输出名称模板。library
和libraryTarget
:用于将你的 bundle 输出为一个库,指定库的名称和导出方式。
通过配置 output
属性,可以灵活地控制 Webpack 打包输出文件的名称、路径和其他相关设置,以满足各种需求。
1.2.3 Loader
Loader 让 webpack 能 够 去 处 理 那 些 非 JavaScript 文 件 (webpack 自 身 只 理 解
JavaScript)
在 Webpack 中,Loader
是一种用于转换模块的机制。在 Webpack 中,一切文件都是模块,而 Loader
则用于告诉 Webpack 如何处理那些非 JavaScript 文件(例如,CSS、图片、字体、TypeScript 等)。通过使用 Loader
,你可以在 import
或 require
模块时预处理文件,并将它们转换为 JavaScript 模块。
使用 Loader 的步骤
- 安装 Loader:通过 npm 安装所需的 Loader。
- 配置 Webpack:在 Webpack 配置文件中定义 Loader 规则。
常用 Loader 示例
1. 处理 CSS 文件的 Loader
安装 style-loader
和 css-loader
:
npm install style-loader css-loader --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
};
这个配置会使用 css-loader
将 CSS 文件解析成 JavaScript 可以理解的模块,然后使用 style-loader
将 CSS 注入到 DOM 中。
2. 处理图像文件的 Loader
安装 file-loader
或 url-loader
:
npm install file-loader url-loader --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource', // 使用内置资源模块
},
],
},
};
asset/resource
会将图像文件单独输出到指定目录,并返回图像的 URL。
3. 处理字体文件的 Loader
字体文件可以使用与图像文件类似的 file-loader
或 url-loader
,这里使用 Webpack 5 内置的资源模块:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource', // 使用内置资源模块
},
],
},
};
4. 处理 Sass 文件的 Loader
安装 sass-loader
、sass
(Dart Sass)、style-loader
和 css-loader
:
npm install sass-loader sass style-loader css-loader --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.scss$/i,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
};
这个配置会使用 sass-loader
将 Sass 文件编译成 CSS,然后使用 css-loader
和 style-loader
处理 CSS。
5. 处理 Babel 的 JavaScript 文件
安装 babel-loader
和 Babel 的相关包:
npm install babel-loader @babel/core @babel/preset-env --save-dev
配置 Webpack 和 Babel:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
],
},
};
6. 处理 TypeScript 文件
安装 ts-loader
和 TypeScript:
npm install ts-loader typescript --save-dev
配置 Webpack 和 TypeScript:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.ts',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
resolve: {
extensions: ['.ts', '.js'],
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
};
Loader 配置详解
每个 Loader 规则通常包含以下几个属性:
- test: 一个正则表达式,匹配文件路径。
- use: 定义使用的 loader,可以是字符串或对象,或 loader 和选项的数组。
- exclude: 排除某些文件路径。
- include: 仅处理某些文件路径。
例如,下面是一个更复杂的 Loader 配置示例:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.scss$/i,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: 'ts-loader',
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
};
总结
- Loader 是 Webpack 用来转换模块的工具,可以将非 JavaScript 文件转换为 JavaScript 模块。
- 安装 Loader:通过 npm 安装所需的 Loader。
- 配置 Webpack:在 Webpack 配置文件中定义 Loader 规则,使用
test
、use
、exclude
、include
等属性来配置 Loader。 - 常见的 Loader:
css-loader
、style-loader
、file-loader
、url-loader
、sass-loader
、babel-loader
、ts-loader
等。
通过合理使用 Loader,可以让 Webpack 处理各种类型的文件,从而实现更复杂和灵活的构建过程。
1.2.4 Plugins
插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,
在 Webpack 中,插件(Plugins)用于执行更广泛的任务,比如打包优化、资源管理和环境变量注入等。插件的功能比 Loader 更强大和灵活,Loader 主要用于转换单个文件,而插件可以直接操作整个构建过程。
使用插件的基本步骤
- 安装插件:通过 npm 安装所需的插件。
- 引入插件:在 Webpack 配置文件中引入插件。
- 配置插件:在 Webpack 配置文件的
plugins
数组中配置插件。
常用插件及其示例
1. HtmlWebpackPlugin
HtmlWebpackPlugin
用于简化 HTML 文件的创建,以便为 Webpack 打包后的文件提供服务。它可以自动生成一个 HTML 文件,并将打包后的文件自动插入其中。
安装插件:
npm install html-webpack-plugin --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/template.html', // 使用的 HTML 模板文件
filename: 'index.html', // 生成的 HTML 文件名
}),
],
};
2. CleanWebpackPlugin
CleanWebpackPlugin
在每次构建前清理输出目录,确保输出目录只包含生产文件。
安装插件:
npm install clean-webpack-plugin --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CleanWebpackPlugin(), // 默认会清理 output.path 目录
],
};
3. MiniCssExtractPlugin
MiniCssExtractPlugin
用于将 CSS 提取到单独的文件中。它支持按需加载 CSS 和 SourceMaps。
安装插件:
npm install mini-css-extract-plugin --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css', // 输出的 CSS 文件名
}),
],
};
4. DefinePlugin
DefinePlugin
允许你在编译时创建配置的全局常量。它非常有用,可以根据不同的环境定义不同的变量值。
安装插件:
DefinePlugin
是 Webpack 内置的插件,不需要安装。
配置 Webpack:
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
],
};
5. HotModuleReplacementPlugin
HotModuleReplacementPlugin
启用模块热替换,允许在运行时更新各种模块,而无需进行完全刷新。
安装插件:
HotModuleReplacementPlugin
是 Webpack 内置的插件,不需要安装。
配置 Webpack:
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
hot: true, // 启用热模块替换
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
};
6. CopyWebpackPlugin
CopyWebpackPlugin
用于将单个文件或整个目录复制到构建目录中。
安装插件:
npm install copy-webpack-plugin --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: 'src/assets', to: 'assets' }, // 将 src/assets 目录复制到 dist/assets
],
}),
],
};
配置示例
以下是一个更完整的 Webpack 配置示例,展示了不同插件的组合使用:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
mode: 'production',
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html',
filename: 'index.html',
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
new CopyWebpackPlugin({
patterns: [
{ from: 'src/assets', to: 'assets' },
],
}),
],
};
总结
- 插件 是 Webpack 中非常强大和灵活的工具,用于执行打包优化、资源管理和环境变量注入等任务。
- 安装插件:通过 npm 安装所需的插件。
- 引入插件:在 Webpack 配置文件中引入插件。
- 配置插件:在 Webpack 配置文件的
plugins
数组中配置插件。
通过合理使用插件,可以极大地增强 Webpack 的功能,满足各种复杂的构建需求。
1.2.5 Mode
模式(Mode)指示 webpack 使用相应模式的配置。
在 Webpack 中,mode
是一个重要的配置项,它可以设置 Webpack 在不同的模式下运行。mode
参数有三个可选值:
development
:开发模式,设置为该模式会启用有用的开发工具和优化构建速度。production
:生产模式,设置为该模式会启用各种优化,如代码压缩、作用域提升和去除未使用代码。none
:不使用任何默认优化或开发工具,提供最大程度的配置灵活性。
mode
配置
你可以在 Webpack 配置文件中设置 mode
,或者在命令行参数中传递。
在配置文件中设置 mode
// webpack.config.js
module.exports = {
mode: 'development', // 'development' or 'production' or 'none'
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
在命令行参数中设置 mode
webpack --mode development
webpack --mode production
webpack --mode none
各模式下的默认配置
development
开发模式下启用的一些默认配置:
process.env.NODE_ENV
被设置为development
- 启用 NamedChunksPlugin 和 NamedModulesPlugin
devtool
被设置为eval
,生成原始源代码 (没有对module
进行优化)- 输出未被压缩的构建
示例:
// webpack.config.js
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
devtool: 'eval', // 快速生成 source maps
};
production
生产模式下启用的一些默认配置:
process.env.NODE_ENV
被设置为production
- 启用模块连接优化 (module concatenation) 和压缩输出
devtool
被设置为source-map
,生成映射到原始源代码的 source maps- 启用各种优化,例如 tree shaking、代码压缩(TerserPlugin)
示例:
// webpack.config.js
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.[contenthash].js',
path: path.resolve(__dirname, 'dist'),
},
devtool: 'source-map', // 生成 source maps 以便调试
};
none
不使用任何默认优化或开发工具,可以最大程度地自定义配置。
示例:
// webpack.config.js
module.exports = {
mode: 'none',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
mode
对构建结果的影响
mode
的值会影响到构建结果的大小、性能和调试体验。例如:
-
开发模式 (
development
):- 启用 source maps,帮助开发者调试代码
- 输出未被压缩的代码,构建速度快,利于快速迭代
- 启用详细的错误信息和警告,帮助发现问题
-
生产模式 (
production
):- 进行代码压缩和优化,减少输出文件的大小
- 启用 tree shaking,去除未使用的代码
- 生成高质量的 source maps,帮助生产环境下的调试
示例
以下是一个完整的 Webpack 配置示例,展示了如何根据不同的模式进行配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
entry: './src/index.js',
output: {
filename: isProduction ? 'bundle.[contenthash].js' : 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
mode: argv.mode || 'development',
devtool: isProduction ? 'source-map' : 'eval',
module: {
rules: [
{
test: /\.css$/i,
use: [
isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader'
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html',
filename: 'index.html',
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(argv.mode),
}),
],
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
hot: !isProduction,
},
};
};
这个配置示例展示了如何根据不同的模式来调整构建输出、开发工具和插件配置。通过设置 mode
,你可以方便地在开发模式和生产模式之间切换,从而提高开发效率和构建质量。
1.2.6 devServer
devServer
是 Webpack 提供的一个开发服务器选项,主要用于提升开发体验。它可以提供一个本地服务器,自动重新加载浏览器,支持热模块替换(Hot Module Replacement, HMR),方便开发者在开发过程中实时查看代码更改效果。
使用 devServer
要使用 devServer
,你需要安装 webpack-dev-server
:
npm install --save-dev webpack-dev-server
配置 devServer
devServer
配置项需要添加到 Webpack 配置文件中。下面是一些常用的配置选项:
基本配置
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
mode: 'development',
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
compress: true, // 启用 gzip 压缩
port: 9000, // 服务器端口号
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
};
热模块替换(HMR)
热模块替换允许在不刷新整个页面的情况下更新应用程序中的模块。这对于保持应用程序状态非常有用。
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
mode: 'development',
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
hot: true, // 启用 HMR
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new webpack.HotModuleReplacementPlugin(), // 启用 HMR 插件
],
};
在你的 JavaScript 文件中,你需要添加一些代码来处理模块更新:
if (module.hot) {
module.hot.accept('./module.js', function () {
console.log('Accepting the updated module!');
// 使用新的模块进行重新渲染等操作
});
}
配置示例
以下是一个更完整的 Webpack 配置示例,包括了各种 devServer
配置项:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
mode: 'development',
devServer: {
static: {
directory: path.join(__dirname, 'dist'), // 提供内容的目录
},
compress: true, // 启用 gzip 压缩
port: 9000, // 服务器端口号
open: true, // 自动打开浏览器
hot: true, // 启用 HMR
historyApiFallback: true, // 适用于单页面应用程序
proxy: { // 代理 API 请求
'/api': 'http://localhost:3000',
},
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new webpack.HotModuleReplacementPlugin(), // 启用 HMR 插件
],
};
常用的 devServer
配置选项
static.directory
:指定静态文件所在的目录。compress
:是否启用 gzip 压缩。port
:指定开发服务器运行的端口。open
:是否在服务器启动后自动打开浏览器。hot
:是否启用热模块替换(HMR)。historyApiFallback
:是否启用 HTML5 历史记录 API 回退功能,适用于单页面应用。proxy
:设置代理,将特定请求代理到另一个服务器。
总结
devServer
是 Webpack 中一个非常强大的工具,它可以极大地提升开发体验。通过使用 devServer
,开发者可以快速启动一个本地服务器,实时查看代码修改效果,甚至在不刷新页面的情况下更新模块。通过合理配置 devServer
,可以更高效地进行前端开发。# Webpack基础学习-Day01
1.1 webpack 是什么
webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler)。
在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/…)都会作为模块处理。
它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。
1.2 webpack 核心概念
1.2.1 Entry
入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图。
在 Webpack 中,entry
属性指定了 Webpack 用来构建其内部依赖图的起点或入口点。换句话说,entry
告诉 Webpack 从哪里开始打包代码。
entry
属性的用法
entry
属性的值可以是以下几种类型:
- 字符串:单个入口文件。
- 数组:多个入口文件,这些文件的内容会被打包到一个 bundle 中。
- 对象:多个入口点,每个入口点会生成一个独立的 bundle。
1. 字符串类型的 entry
这是最简单的用法,指定一个单一的入口文件:
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
在这种情况下,Webpack 从 ./src/index.js
开始构建依赖图,并将所有模块打包到 bundle.js
文件中。
2. 数组类型的 entry
如果你有多个文件需要作为入口,但希望将它们打包到一个 bundle 中,可以使用数组:
module.exports = {
entry: ['./src/index.js', './src/anotherModule.js'],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
这种情况下,index.js
和 anotherModule.js
会被打包到同一个 bundle.js
文件中。
3. 对象类型的 entry
对象类型的 entry
允许你定义多个独立的入口点,每个入口点会生成一个独立的 bundle:
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
在这种情况下,会生成两个独立的 bundle 文件:app.bundle.js
和 admin.bundle.js
。[name]
是一个占位符,会被 entry
对象的键替换。
高级用法
动态入口
可以通过函数返回一个对象来动态生成入口点:
module.exports = {
entry: () => {
const entries = {
main: './src/main.js',
};
if (process.env.NODE_ENV === 'development') {
entries.dev = './src/dev.js';
}
return entries;
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
这种方式允许根据环境或其他条件动态配置入口点。
使用多个入口和 SplitChunks 插件
通过配合 SplitChunksPlugin
,可以将共享代码提取到一个独立的 chunk 中:
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
splitChunks: {
chunks: 'all',
},
},
};
这种配置会将 app.js
和 admin.js
中的共享模块提取到一个公共的 bundle 中,从而减少重复代码。
配置示例
以下是一个更完整的 Webpack 配置示例,展示了不同类型的 entry
配置和一些常见的插件配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].[contenthash].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html',
chunks: ['app'], // 仅包含 app chunk
}),
new HtmlWebpackPlugin({
template: './src/admin-template.html',
filename: 'admin.html',
chunks: ['admin'], // 仅包含 admin chunk
}),
],
optimization: {
splitChunks: {
chunks: 'all',
},
},
};
总结
entry
属性是 Webpack 配置中的一个重要部分,它定义了 Webpack 构建的入口点。通过灵活使用字符串、数组和对象类型的 entry
,你可以实现不同的构建策略和优化代码拆分。结合 Webpack 的其他特性(如插件和优化选项),可以构建高效、可维护的前端项目。
1.2.2 Output
输出(Output)指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名。
output
属性是 Webpack 配置中的一个关键部分,它定义了打包后输出文件的相关设置。通过配置 output
,你可以指定打包文件的名称、路径、公共路径等。
基本配置
1. filename
filename
用于指定输出文件的名称。可以使用占位符来生成动态文件名。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js', // 输出文件名
path: path.resolve(__dirname, 'dist'), // 输出路径
},
};
常用的占位符包括:
[name]
: 入口点名称[id]
: chunk ID[hash]
: 编译时的唯一 hash[chunkhash]
: chunk 的 hash[contenthash]
: 文件内容的 hash
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].[contenthash].js', // 动态生成文件名
path: path.resolve(__dirname, 'dist'),
},
};
2. path
path
用于指定输出目录的绝对路径。通常使用 Node.js 的 path
模块来生成绝对路径。
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'), // 使用绝对路径
},
};
3. publicPath
publicPath
用于指定输出解析文件的公共 URL 地址。通常用于配置 CDN 地址或开发服务器地址。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/', // 公共路径,通常用于配置 CDN 地址
},
};
高级配置
1. chunkFilename
chunkFilename
用于指定按需加载的 chunk 文件的名称模板。类似于 filename
,可以使用占位符。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
chunkFilename: '[name].[contenthash].js', // 按需加载的 chunk 文件名
},
};
2. assetModuleFilename
assetModuleFilename
用于指定通过资源模块(如图像、字体等)处理的文件的输出文件名模板。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: 'assets/[name].[hash][ext]', // 资源模块文件名
},
};
3. library
和 libraryTarget
library
和 libraryTarget
用于将你的 bundle 输出为一个库。
library
指定库的名称。libraryTarget
指定导出库的方式(如var
,umd
,commonjs2
等)。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
library: 'MyLibrary', // 库名称
libraryTarget: 'umd', // 输出库的方式
},
};
常见示例
示例 1:简单的单入口点配置
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
示例 2:多入口点配置
const path = require('path');
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
},
};
示例 3:配置公共路径
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'https://cdn.example.com/assets/', // 使用 CDN 地址
},
};
示例 4:配置资源模块输出
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: 'images/[name].[hash][ext]', // 资源模块文件名
},
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
};
详细解释
filename
:指定输出文件的名称,可以使用占位符动态生成文件名。path
:指定输出目录的绝对路径,通常使用 Node.js 的path.resolve
方法。publicPath
:指定公共路径,通常用于配置 CDN 地址或开发服务器地址。chunkFilename
:指定按需加载的 chunk 文件的名称模板。assetModuleFilename
:指定资源模块处理的文件输出名称模板。library
和libraryTarget
:用于将你的 bundle 输出为一个库,指定库的名称和导出方式。
通过配置 output
属性,可以灵活地控制 Webpack 打包输出文件的名称、路径和其他相关设置,以满足各种需求。
1.2.3 Loader
Loader 让 webpack 能 够 去 处 理 那 些 非 JavaScript 文 件 (webpack 自 身 只 理 解
JavaScript)
在 Webpack 中,Loader
是一种用于转换模块的机制。在 Webpack 中,一切文件都是模块,而 Loader
则用于告诉 Webpack 如何处理那些非 JavaScript 文件(例如,CSS、图片、字体、TypeScript 等)。通过使用 Loader
,你可以在 import
或 require
模块时预处理文件,并将它们转换为 JavaScript 模块。
使用 Loader 的步骤
- 安装 Loader:通过 npm 安装所需的 Loader。
- 配置 Webpack:在 Webpack 配置文件中定义 Loader 规则。
常用 Loader 示例
1. 处理 CSS 文件的 Loader
安装 style-loader
和 css-loader
:
npm install style-loader css-loader --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
};
这个配置会使用 css-loader
将 CSS 文件解析成 JavaScript 可以理解的模块,然后使用 style-loader
将 CSS 注入到 DOM 中。
2. 处理图像文件的 Loader
安装 file-loader
或 url-loader
:
npm install file-loader url-loader --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource', // 使用内置资源模块
},
],
},
};
asset/resource
会将图像文件单独输出到指定目录,并返回图像的 URL。
3. 处理字体文件的 Loader
字体文件可以使用与图像文件类似的 file-loader
或 url-loader
,这里使用 Webpack 5 内置的资源模块:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource', // 使用内置资源模块
},
],
},
};
4. 处理 Sass 文件的 Loader
安装 sass-loader
、sass
(Dart Sass)、style-loader
和 css-loader
:
npm install sass-loader sass style-loader css-loader --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.scss$/i,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
};
这个配置会使用 sass-loader
将 Sass 文件编译成 CSS,然后使用 css-loader
和 style-loader
处理 CSS。
5. 处理 Babel 的 JavaScript 文件
安装 babel-loader
和 Babel 的相关包:
npm install babel-loader @babel/core @babel/preset-env --save-dev
配置 Webpack 和 Babel:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
],
},
};
6. 处理 TypeScript 文件
安装 ts-loader
和 TypeScript:
npm install ts-loader typescript --save-dev
配置 Webpack 和 TypeScript:
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.ts',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
resolve: {
extensions: ['.ts', '.js'],
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
};
Loader 配置详解
每个 Loader 规则通常包含以下几个属性:
- test: 一个正则表达式,匹配文件路径。
- use: 定义使用的 loader,可以是字符串或对象,或 loader 和选项的数组。
- exclude: 排除某些文件路径。
- include: 仅处理某些文件路径。
例如,下面是一个更复杂的 Loader 配置示例:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.scss$/i,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: 'ts-loader',
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
};
总结
- Loader 是 Webpack 用来转换模块的工具,可以将非 JavaScript 文件转换为 JavaScript 模块。
- 安装 Loader:通过 npm 安装所需的 Loader。
- 配置 Webpack:在 Webpack 配置文件中定义 Loader 规则,使用
test
、use
、exclude
、include
等属性来配置 Loader。 - 常见的 Loader:
css-loader
、style-loader
、file-loader
、url-loader
、sass-loader
、babel-loader
、ts-loader
等。
通过合理使用 Loader,可以让 Webpack 处理各种类型的文件,从而实现更复杂和灵活的构建过程。
1.2.4 Plugins
插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,
在 Webpack 中,插件(Plugins)用于执行更广泛的任务,比如打包优化、资源管理和环境变量注入等。插件的功能比 Loader 更强大和灵活,Loader 主要用于转换单个文件,而插件可以直接操作整个构建过程。
使用插件的基本步骤
- 安装插件:通过 npm 安装所需的插件。
- 引入插件:在 Webpack 配置文件中引入插件。
- 配置插件:在 Webpack 配置文件的
plugins
数组中配置插件。
常用插件及其示例
1. HtmlWebpackPlugin
HtmlWebpackPlugin
用于简化 HTML 文件的创建,以便为 Webpack 打包后的文件提供服务。它可以自动生成一个 HTML 文件,并将打包后的文件自动插入其中。
安装插件:
npm install html-webpack-plugin --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/template.html', // 使用的 HTML 模板文件
filename: 'index.html', // 生成的 HTML 文件名
}),
],
};
2. CleanWebpackPlugin
CleanWebpackPlugin
在每次构建前清理输出目录,确保输出目录只包含生产文件。
安装插件:
npm install clean-webpack-plugin --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CleanWebpackPlugin(), // 默认会清理 output.path 目录
],
};
3. MiniCssExtractPlugin
MiniCssExtractPlugin
用于将 CSS 提取到单独的文件中。它支持按需加载 CSS 和 SourceMaps。
安装插件:
npm install mini-css-extract-plugin --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css', // 输出的 CSS 文件名
}),
],
};
4. DefinePlugin
DefinePlugin
允许你在编译时创建配置的全局常量。它非常有用,可以根据不同的环境定义不同的变量值。
安装插件:
DefinePlugin
是 Webpack 内置的插件,不需要安装。
配置 Webpack:
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
],
};
5. HotModuleReplacementPlugin
HotModuleReplacementPlugin
启用模块热替换,允许在运行时更新各种模块,而无需进行完全刷新。
安装插件:
HotModuleReplacementPlugin
是 Webpack 内置的插件,不需要安装。
配置 Webpack:
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
hot: true, // 启用热模块替换
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
};
6. CopyWebpackPlugin
CopyWebpackPlugin
用于将单个文件或整个目录复制到构建目录中。
安装插件:
npm install copy-webpack-plugin --save-dev
配置 Webpack:
// webpack.config.js
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: 'src/assets', to: 'assets' }, // 将 src/assets 目录复制到 dist/assets
],
}),
],
};
配置示例
以下是一个更完整的 Webpack 配置示例,展示了不同插件的组合使用:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
mode: 'production',
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html',
filename: 'index.html',
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
new CopyWebpackPlugin({
patterns: [
{ from: 'src/assets', to: 'assets' },
],
}),
],
};
总结
- 插件 是 Webpack 中非常强大和灵活的工具,用于执行打包优化、资源管理和环境变量注入等任务。
- 安装插件:通过 npm 安装所需的插件。
- 引入插件:在 Webpack 配置文件中引入插件。
- 配置插件:在 Webpack 配置文件的
plugins
数组中配置插件。
通过合理使用插件,可以极大地增强 Webpack 的功能,满足各种复杂的构建需求。
1.2.5 Mode
模式(Mode)指示 webpack 使用相应模式的配置。
在 Webpack 中,mode
是一个重要的配置项,它可以设置 Webpack 在不同的模式下运行。mode
参数有三个可选值:
development
:开发模式,设置为该模式会启用有用的开发工具和优化构建速度。production
:生产模式,设置为该模式会启用各种优化,如代码压缩、作用域提升和去除未使用代码。none
:不使用任何默认优化或开发工具,提供最大程度的配置灵活性。
mode
配置
你可以在 Webpack 配置文件中设置 mode
,或者在命令行参数中传递。
在配置文件中设置 mode
// webpack.config.js
module.exports = {
mode: 'development', // 'development' or 'production' or 'none'
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
在命令行参数中设置 mode
webpack --mode development
webpack --mode production
webpack --mode none
各模式下的默认配置
development
开发模式下启用的一些默认配置:
process.env.NODE_ENV
被设置为development
- 启用 NamedChunksPlugin 和 NamedModulesPlugin
devtool
被设置为eval
,生成原始源代码 (没有对module
进行优化)- 输出未被压缩的构建
示例:
// webpack.config.js
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
devtool: 'eval', // 快速生成 source maps
};
production
生产模式下启用的一些默认配置:
process.env.NODE_ENV
被设置为production
- 启用模块连接优化 (module concatenation) 和压缩输出
devtool
被设置为source-map
,生成映射到原始源代码的 source maps- 启用各种优化,例如 tree shaking、代码压缩(TerserPlugin)
示例:
// webpack.config.js
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.[contenthash].js',
path: path.resolve(__dirname, 'dist'),
},
devtool: 'source-map', // 生成 source maps 以便调试
};
none
不使用任何默认优化或开发工具,可以最大程度地自定义配置。
示例:
// webpack.config.js
module.exports = {
mode: 'none',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
mode
对构建结果的影响
mode
的值会影响到构建结果的大小、性能和调试体验。例如:
-
开发模式 (
development
):- 启用 source maps,帮助开发者调试代码
- 输出未被压缩的代码,构建速度快,利于快速迭代
- 启用详细的错误信息和警告,帮助发现问题
-
生产模式 (
production
):- 进行代码压缩和优化,减少输出文件的大小
- 启用 tree shaking,去除未使用的代码
- 生成高质量的 source maps,帮助生产环境下的调试
示例
以下是一个完整的 Webpack 配置示例,展示了如何根据不同的模式进行配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
entry: './src/index.js',
output: {
filename: isProduction ? 'bundle.[contenthash].js' : 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
mode: argv.mode || 'development',
devtool: isProduction ? 'source-map' : 'eval',
module: {
rules: [
{
test: /\.css$/i,
use: [
isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader'
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html',
filename: 'index.html',
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(argv.mode),
}),
],
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
hot: !isProduction,
},
};
};
这个配置示例展示了如何根据不同的模式来调整构建输出、开发工具和插件配置。通过设置 mode
,你可以方便地在开发模式和生产模式之间切换,从而提高开发效率和构建质量。
1.2.6 devServer
devServer
是 Webpack 提供的一个开发服务器选项,主要用于提升开发体验。它可以提供一个本地服务器,自动重新加载浏览器,支持热模块替换(Hot Module Replacement, HMR),方便开发者在开发过程中实时查看代码更改效果。
使用 devServer
要使用 devServer
,你需要安装 webpack-dev-server
:
npm install --save-dev webpack-dev-server
配置 devServer
devServer
配置项需要添加到 Webpack 配置文件中。下面是一些常用的配置选项:
基本配置
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
mode: 'development',
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
compress: true, // 启用 gzip 压缩
port: 9000, // 服务器端口号
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
};
热模块替换(HMR)
热模块替换允许在不刷新整个页面的情况下更新应用程序中的模块。这对于保持应用程序状态非常有用。
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
mode: 'development',
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
hot: true, // 启用 HMR
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new webpack.HotModuleReplacementPlugin(), // 启用 HMR 插件
],
};
在你的 JavaScript 文件中,你需要添加一些代码来处理模块更新:
if (module.hot) {
module.hot.accept('./module.js', function () {
console.log('Accepting the updated module!');
// 使用新的模块进行重新渲染等操作
});
}
配置示例
以下是一个更完整的 Webpack 配置示例,包括了各种 devServer
配置项:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
mode: 'development',
devServer: {
static: {
directory: path.join(__dirname, 'dist'), // 提供内容的目录
},
compress: true, // 启用 gzip 压缩
port: 9000, // 服务器端口号
open: true, // 自动打开浏览器
hot: true, // 启用 HMR
historyApiFallback: true, // 适用于单页面应用程序
proxy: { // 代理 API 请求
'/api': 'http://localhost:3000',
},
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new webpack.HotModuleReplacementPlugin(), // 启用 HMR 插件
],
};
常用的 devServer
配置选项
static.directory
:指定静态文件所在的目录。compress
:是否启用 gzip 压缩。port
:指定开发服务器运行的端口。open
:是否在服务器启动后自动打开浏览器。hot
:是否启用热模块替换(HMR)。historyApiFallback
:是否启用 HTML5 历史记录 API 回退功能,适用于单页面应用。proxy
:设置代理,将特定请求代理到另一个服务器。
总结
devServer
是 Webpack 中一个非常强大的工具,它可以极大地提升开发体验。通过使用 devServer
,开发者可以快速启动一个本地服务器,实时查看代码修改效果,甚至在不刷新页面的情况下更新模块。通过合理配置 devServer
,可以更高效地进行前端开发。