MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Webpack 安装与项目初始化流程

2021-01-114.7k 阅读

Webpack 简介

Webpack 是一款现代 JavaScript 应用程序的静态模块打包工具。在前端开发中,我们会面临各种各样的资源,例如 JavaScript、CSS、图片等。随着项目规模的扩大,如何高效地管理和整合这些资源变得至关重要。Webpack 应运而生,它能够将这些不同类型的资源视为一个个模块,并根据它们之间的依赖关系进行分析和打包,最终生成在浏览器中可以直接运行的静态资源。

Webpack 的核心功能包括模块打包、代码拆分、加载器(Loader)和插件(Plugin)系统。模块打包可以将多个模块组合成一个或多个 bundle 文件;代码拆分允许我们将代码按需加载,提高应用程序的加载性能;Loader 用于处理不同类型的文件,比如将 CSS 文件转化为 JavaScript 可以处理的模块;Plugin 则提供了更广泛的功能扩展,例如压缩代码、自动生成 HTML 文件等。

环境准备

在开始安装 Webpack 之前,我们需要确保本地开发环境具备以下条件:

安装 Node.js

Webpack 是基于 Node.js 运行的,所以首先要安装 Node.js。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,它让 JavaScript 能够在服务器端运行。

我们可以从 Node.js 官方网站(https://nodejs.org/)下载适合自己操作系统的安装包进行安装。安装完成后,打开命令行工具,输入以下命令检查 Node.js 是否安装成功:

node -v

如果成功安装,会输出版本号,例如 v14.17.0

安装 npm

npm(Node Package Manager)是 Node.js 的默认包管理工具,随着 Node.js 的安装会一同安装。npm 用于管理项目中的依赖包,包括安装、更新和卸载等操作。同样在命令行中输入以下命令检查 npm 是否安装成功:

npm -v

输出版本号即表示安装成功,例如 6.14.13

Webpack 安装

Webpack 有两种安装方式:全局安装和局部安装。

全局安装

全局安装 Webpack 可以在任何项目中直接使用 Webpack 命令。在命令行中执行以下命令进行全局安装:

npm install -g webpack webpack -cli

这里 -g 表示全局安装,webpack 是核心包,webpack -cli 是命令行工具,用于在终端中执行 Webpack 相关命令。

全局安装完成后,在任何目录下都可以通过 webpack -v 命令检查 Webpack 是否安装成功并查看版本号。

然而,全局安装存在一些问题。不同项目可能需要不同版本的 Webpack,全局安装可能会导致版本冲突。并且,全局安装的 Webpack 可能无法与项目中的其他依赖包完美兼容。所以,一般情况下更推荐局部安装。

局部安装

局部安装 Webpack 是将 Webpack 安装到具体的项目目录中,这样每个项目可以独立管理自己的 Webpack 版本。

首先,在本地创建一个新的项目目录,例如 my - webpack - project,然后进入该目录:

mkdir my - webpack - project
cd my - webpack - project

接着,初始化项目,执行以下命令:

npm init -y

npm init -y 会使用默认配置快速初始化一个 package.json 文件,该文件用于管理项目的元数据和依赖包。

之后,执行局部安装命令:

npm install webpack webpack -cli --save - dev

--save - dev 表示将 Webpack 和 webpack - cli 安装为开发依赖,开发依赖通常用于项目开发过程中的工具和辅助库,不会被部署到生产环境。

安装完成后,可以在项目目录下的 node_modules 文件夹中找到 Webpack 和相关依赖,并且 package.json 文件中会新增 devDependencies 字段,其中包含了 Webpack 和 webpack - cli 的版本信息。

项目初始化流程

在完成 Webpack 的安装后,我们开始初始化一个 Webpack 项目。

创建项目结构

在项目根目录下,我们创建以下基本目录结构:

my - webpack - project
├── src
│   └── index.js
├── dist
├── webpack.config.js
└── package.json
  • src 目录:用于存放项目的源代码,index.js 是项目的入口文件,所有模块的依赖关系从这个文件开始构建。
  • dist 目录:用于存放 Webpack 打包输出的文件,在项目初始化时这个目录可以为空,Webpack 会在打包过程中自动创建并生成文件。
  • webpack.config.js:Webpack 的配置文件,用于配置 Webpack 的各种参数和功能,例如入口、出口、加载器、插件等。
  • package.json:项目的配置文件,管理项目的依赖包和脚本命令等。

编写入口文件

src/index.js 文件中,我们编写一个简单的 JavaScript 代码示例:

function add(a, b) {
    return a + b;
}
const result = add(1, 2);
console.log(result);

这段代码定义了一个简单的加法函数 add,并调用它计算 1 + 2 的结果,然后在控制台打印出来。

配置 Webpack

在项目根目录下创建 webpack.config.js 文件,并编写以下基本配置:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    }
};
  • entry:指定项目的入口文件路径,这里是 ./src/index.js。Webpack 会从这个文件开始分析模块依赖关系。
  • output:配置输出的相关信息。path 使用 path.resolve(__dirname, 'dist') 获取 dist 目录的绝对路径,__dirname 表示当前文件所在目录,即项目根目录。filename 指定输出文件的名称为 bundle.js

配置 npm 脚本

打开 package.json 文件,在 scripts 字段中添加以下脚本:

{
    "scripts": {
        "build": "webpack --config webpack.config.js"
    }
}

这里定义了一个名为 build 的脚本,执行 npm run build 命令时,会调用 Webpack 并使用 webpack.config.js 配置文件进行打包。

执行打包

在命令行中进入项目根目录,执行以下命令:

npm run build

Webpack 会根据配置文件的设置,从入口文件开始分析依赖关系,将所有相关模块打包成 bundle.js 文件,并输出到 dist 目录中。

打包完成后,在 dist 目录下会生成 bundle.js 文件。虽然我们目前的示例很简单,但随着项目的扩展,Webpack 可以处理更复杂的模块依赖和资源整合。

处理不同类型文件

在实际项目中,我们不仅会有 JavaScript 文件,还会涉及到 CSS、图片等其他类型的文件。Webpack 通过加载器(Loader)来处理这些不同类型的文件。

处理 CSS 文件

要在项目中使用 CSS 文件,我们需要安装 style - loadercss - loadercss - loader 用于解析 CSS 文件中的 @importurl() 等语句,style - loader 则将 CSS 样式插入到 DOM 中。

执行以下安装命令:

npm install style - loader css - loader --save - dev

安装完成后,修改 webpack.config.js 文件,添加对 CSS 文件的处理:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style - loader', 'css - loader']
            }
        ]
    }
};
  • module.rules 用于配置加载器规则。
  • test 使用正则表达式 /\.css$/ 匹配所有以 .css 结尾的文件。
  • use 数组指定了处理 CSS 文件的加载器,顺序是从右到左(从下到上),先使用 css - loader 处理,再使用 style - loader

接下来,在 src 目录下创建一个 styles.css 文件,添加一些简单的样式:

body {
    background - color: lightblue;
}

然后在 src/index.js 文件中引入 styles.css

import './styles.css';

function add(a, b) {
    return a + b;
}
const result = add(1, 2);
console.log(result);

再次执行 npm run build 命令,Webpack 会将 CSS 文件的内容整合到打包后的 bundle.js 文件中,并在页面加载时将样式应用到页面上。

处理图片文件

处理图片文件可以使用 file - loaderurl - loaderfile - loader 会将图片文件复制到输出目录,并返回图片的路径;url - loader 类似,但当图片较小时,可以将图片转换为 Data URL 嵌入到代码中,减少 HTTP 请求。

先安装 file - loader

npm install file - loader --save - dev

修改 webpack.config.js,添加图片处理规则:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style - loader', 'css - loader']
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'file - loader',
                        options: {
                            name: 'images/[name].[ext]'
                        }
                    }
                ]
            }
        ]
    }
};
  • test 正则表达式匹配 .png.jpg.gif 格式的图片文件。
  • options.name 配置输出图片的路径和文件名,images/[name].[ext] 表示将图片输出到 dist/images 目录下,文件名保持不变。

src 目录下创建一个 images 目录,并放入一张图片,例如 logo.png。然后在 src/index.js 中引入图片:

import './styles.css';
import logo from './images/logo.png';

function add(a, b) {
    return a + b;
}
const result = add(1, 2);
console.log(result);
console.log(logo);

执行 npm run build 后,图片会被复制到 dist/images 目录下,并且在 bundle.js 中会有对图片路径的引用。

使用插件扩展功能

Webpack 的插件(Plugin)可以在 Webpack 构建过程的不同阶段执行各种任务,进一步扩展 Webpack 的功能。

HtmlWebpackPlugin

HtmlWebpackPlugin 用于自动生成 HTML 文件,并将打包后的 JavaScript 文件插入到 HTML 中。

安装 HtmlWebpackPlugin

npm install html - webpack - plugin --save - dev

修改 webpack.config.js

const path = require('path');
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: ['style - loader', 'css - loader']
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'file - loader',
                        options: {
                            name: 'images/[name].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ]
};
  • plugins 数组用于配置插件。
  • new HtmlWebpackPlugin() 创建一个 HtmlWebpackPlugin 实例。template 指定使用 src/index.html 作为模板文件。

src 目录下创建 index.html 文件:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF - 8">
    <meta name="viewport" content="width=device - width, initial - scale=1.0">
    <title>Webpack Project</title>
</head>

<body>

</body>

</html>

再次执行 npm run build,Webpack 会在 dist 目录下生成 index.html 文件,并将 bundle.js 插入到 <body> 标签中。

MiniCssExtractPlugin

MiniCssExtractPlugin 用于将 CSS 从 JavaScript 中提取出来,生成单独的 CSS 文件,这样在生产环境中可以提高加载性能。

安装 MiniCssExtractPlugin

npm install mini - css - extract - plugin --save - dev

修改 webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html - webpack - plugin');
const MiniCssExtractPlugin = require('mini - css - extract - plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css - loader']
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'file - loader',
                        options: {
                            name: 'images/[name].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new MiniCssExtractPlugin({
            filename:'styles.css'
        })
    ]
};
  • module.rules 中处理 CSS 文件的 use 数组中,将 style - loader 替换为 MiniCssExtractPlugin.loader
  • plugins 数组中添加 new MiniCssExtractPlugin() 实例,并通过 filename 配置输出的 CSS 文件名称为 styles.css

执行 npm run build 后,CSS 会被提取到 dist/styles.css 文件中,并且 index.html 会自动引入这个 CSS 文件。

开发服务器

在开发过程中,频繁地手动执行打包命令并刷新浏览器查看效果非常繁琐。Webpack 提供了 webpack - dev - server 来解决这个问题,它可以启动一个本地开发服务器,实时自动刷新页面。

安装 webpack - dev - server

npm install webpack - dev - server --save - dev

修改 package.jsonscripts 字段,添加开发服务器脚本:

{
    "scripts": {
        "build": "webpack --config webpack.config.js",
        "start": "webpack - dev - server --config webpack.config.js"
    }
}

执行 npm run start 命令,webpack - dev - server 会启动一个本地服务器,默认监听 http://localhost:8080。当你修改源代码时,服务器会自动重新打包并刷新浏览器页面,大大提高开发效率。

优化配置

在项目开发过程中,优化 Webpack 配置可以提高打包速度和输出文件的质量。

代码压缩

在生产环境中,我们通常需要对代码进行压缩以减小文件体积。Webpack 可以使用 terser - webpack - plugin 来压缩 JavaScript 代码。

安装 terser - webpack - plugin

npm install terser - webpack - plugin --save - dev

修改 webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html - webpack - plugin');
const MiniCssExtractPlugin = require('mini - css - extract - plugin');
const TerserPlugin = require('terser - webpack - plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css - loader']
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'file - loader',
                        options: {
                            name: 'images/[name].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new MiniCssExtractPlugin({
            filename:'styles.css'
        })
    ],
    optimization: {
        minimizer: [
            new TerserPlugin()
        ]
    }
};

optimization.minimizer 数组中添加 new TerserPlugin() 实例,Webpack 在打包时会自动使用该插件压缩 JavaScript 代码。

缓存

Webpack 支持缓存机制,可以提高后续打包的速度。在 webpack.config.js 中添加以下配置:

module.exports = {
    // 其他配置...
    cache: {
        type: 'filesystem',
        buildDependencies: {
            config: [__filename]
        }
    }
};
  • cache.type 设置为 filesystem 表示使用文件系统缓存。
  • buildDependencies.config 表示当 webpack.config.js 文件变化时,缓存才会失效。

多入口和代码拆分

随着项目规模的增大,可能需要多个入口文件,并且将代码进行拆分,实现按需加载。

多入口

假设我们有两个页面,分别有各自的入口文件 src/page1.jssrc/page2.js。修改 webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html - webpack - plugin');
const MiniCssExtractPlugin = require('mini - css - extract - plugin');

module.exports = {
    entry: {
        page1: './src/page1.js',
        page2: './src/page2.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css - loader']
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'file - loader',
                        options: {
                            name: 'images/[name].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/page1.html',
            filename: 'page1.html',
            chunks: ['page1']
        }),
        new HtmlWebpackPlugin({
            template: './src/page2.html',
            filename: 'page2.html',
            chunks: ['page2']
        }),
        new MiniCssExtractPlugin({
            filename:'styles.css'
        })
    ]
};
  • entry 变为一个对象,指定两个入口文件 page1page2
  • output.filename 使用 [name].bundle.js[name] 会被替换为入口文件的名称,即 page1.bundle.jspage2.bundle.js
  • HtmlWebpackPlugin 配置两个实例,分别对应两个页面的模板文件,并通过 chunks 指定对应的入口文件。

代码拆分

代码拆分可以将重复的代码提取出来,避免重复加载。Webpack 提供了 splitChunks 配置来实现代码拆分。

修改 webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html - webpack - plugin');
const MiniCssExtractPlugin = require('mini - css - extract - plugin');

module.exports = {
    entry: {
        page1: './src/page1.js',
        page2: './src/page2.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css - loader']
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'file - loader',
                        options: {
                            name: 'images/[name].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/page1.html',
            filename: 'page1.html',
            chunks: ['page1']
        }),
        new HtmlWebpackPlugin({
            template: './src/page2.html',
            filename: 'page2.html',
            chunks: ['page2']
        }),
        new MiniCssExtractPlugin({
            filename:'styles.css'
        })
    ],
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    }
};

optimization.splitChunks.chunks: 'all' 表示对所有类型的 chunks(入口 chunks 和异步 chunks)都进行代码拆分。Webpack 会自动提取重复的代码到单独的文件中,例如 vendors~page1~page2.bundle.js,多个页面可以共享这些代码,提高加载性能。

通过以上步骤,我们详细介绍了 Webpack 的安装与项目初始化流程,以及如何处理不同类型文件、使用插件、优化配置和实现多入口与代码拆分等内容。Webpack 是一个功能强大且灵活的工具,在实际项目中,根据具体需求进一步深入学习和优化配置,可以为前端开发带来更高的效率和更好的用户体验。