给我30分钟带你快速入门WebPack

1,916 阅读9分钟

什么是webpack

简单来说,webpack就是一个打包工具,可以将相互依赖的html,css,js以及图片字体等资源文件,经过处理打包成一个可执行的项目文件。

本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个依赖图,然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。

接下来我将通过一个简单的例子来带你感受一下webpack打包的过程

环境初始化

首先我们创建一个文件夹,用终端打开该文件夹输入指令npm init -y初始化项目环境,其中-y表示的是所有选项均使用默认值。

然后再执行npm add webpack webpack-cli --dev将webpack安装到开发环境中,执行完以上操作我们将得到以下文件目录:

image.png

接下来我们新键一个src文件夹,在src文件夹中新键一个index.js文件

在该文件夹中编写简单的一段代码:

console.log('hello world')

然后将index.js文件夹引入index.html

image.png 在浏览器中打开,可以看到:

image.png

这样就说明已经成功将index.js文件夹引入index.html中,接下来我们开始打包这个文件。

执行指令:npx webpack,可以看到在dist文件夹中生成了main.js文件

image.png

为什么生成的main.js文件呢?这个在后面我们会详细介绍,这主要是因为webpack配置文件中的output属性,这个属性用来告诉webpack在哪里输出它所创建的bundle,以及如何命名这些文件,输出文件的默认值是./dist/main.js,其他的文件生成默认放在./dist文件夹中。

接下来我们一起体验下webpack整合代码的功能,在src目录下新键一个文件data.js

export function getData() {
     return [
        {
            name: "张三",
            age: 18
        },
        {
            name: "李四",
            age: 19
        },
        {
            name: "王五",
            age: 20
        }
    ]
}

然后修改index.js代码,在index.js中调用这个getData函数

import { getData } from "./data.js";
console.log(getData())

然后再执行npx webpack打包代码 image.png 可以看到main.js中的代码简化了,说明webpack智能地判断了代码的逻辑,通过import获取了代码,知道我们只打印了这个数组,所以整合到一起的代码就如上图所示

配置webpack

在配置webpack前,让我们先了解一下webpack中的一些核心概念

入口(entry)

入口起点(Entry Point)是告诉 webpack 从哪个文件开始打包,构建内部的依赖关系图。当确定了入口起点后,webpack 将从这个文件出发,追踪并识别出所有它直接或间接依赖的模块和库。这样,webpack 就能知道整个项目中哪些资源是必需的,并将它们组织起来。

默认值是 ./src/index.js,但我们可以通过在 webpack.config.js 中配置 entry 属性,来指定一个(或多个)不同的入口起点。例如:

module.exports = {
  entry: './xxx/xxx/xxx/xxx/xxx.js',
};

输出(output)

output 配置项是指令 webpack 如何处理和命名打包后的文件。它定义了打包文件的输出位置及文件名。默认情况下,主输出文件会被放置在 ./dist/main.js 路径下,而其他的生成文件则会被存放在 ./dist 目录中。通过调整 output 配置,你可以自定义输出文件的具体路径和名称,以满足项目的实际需求。

const path = require('path');
module.exports = {
  entry: './xxx/xxx/xxx/xxx/xxx.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'dist.js',
  },
};

在上述配置中,output.filename 和 output.path 这两个属性是用来指定 webpack 打包后文件的名称和存放位置的。具体来说,filename 定义了输出文件的名称,而 path 则指明了这些文件应该被放置的目录。

提到的 path 模块,它是 Node.js 的一个内置核心模块,主要用于处理和转换文件路径。在 webpack 配置中引入 path 模块,通常是为了确保路径在不同操作系统上都能正确解析,因为不同的操作系统对路径的表示方式有所不同(例如,Windows 使用反斜杠 \,而 Unix 系统使用正斜杠 /)。通过 path 模块提供的方法,如 path.resolve 或 path.join,可以构建出适用于当前运行环境的绝对路径,从而保证 webpack 配置的兼容性和健壮性。

loader

webpack 默认仅支持解析 JavaScriptJSON 文件。为了能够处理其他类型的文件,比如 CSS、图片或字体文件等,我们需要借助于 loaderloader 是 webpack 中的一个重要概念,它允许 webpack 处理非 JavaScript 文件,并将这些文件转换成能够在应用中使用的模块。一旦经过 loader 的转换,这些文件就可以被添加到 webpack 的依赖图中,成为构建流程的一部分。简单来说,loader 扩展了 webpack 的功能,使其能够理解和处理更广泛类型的文件,从而适应更多样的开发需求。

在webpack配置中,loader有两个属性:

  1. test属性,识别出哪些文件会被转换。
  2. use属性,定义在进行转换时,应该使用哪个loader
const path = require('path');

module.exports = {
   output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'dist.js',
  },
   module: {
        rules: [
            {
                test: /\.css$/i,
                use: ['style-loader', 'css-loader'],
            },
            {
                test: /\.(png|svg|jpg|jpeg|gif)$/i,
                type: 'asset/resource'
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env'],
                    },
                }
            }
        ],
    }
};

在上述配置中,module 对象内的 rules 属性定义了一系列规则,用于指导 webpack 编译器如何处理不同类型的文件。每条规则都包含两个必要的属性:test 和 use。

test 属性:这是一个匹配条件,通常使用正则表达式来指定哪些文件应该被这条规则处理。例如,如果想让规则应用于所有的 .css 文件,可以设置 test: /.css$/。

use 属性:这指定了当文件符合 test 属性定义的条件时,应该应用哪一个或哪几个 loader 来处理这些文件。use 可以是一个字符串,代表单个 loader 的名称;也可以是一个数组,包含多个 loader,按照从右向左的顺序依次执行。

插件(plugin)

loader主要用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量等。

使用插件的步骤简要如下:

  1. 引入插件:使用 require() 引入你需要的插件。

  2. 配置插件:在 webpack 配置对象的 plugins 数组中添加插件。如果插件支持配置选项,可以通过构造函数创建实例并传入选项。

  3. 多次使用:若需在同一配置文件中多次使用同一插件,每次都要用 new 关键字创建新的实例。

const HtmlWebpackPlugin = require('html-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer');
module.exports = {
    plugins: [new HtmlWebpackPlugin({
        title: '列表'
    }),
    new BundleAnalyzerPlugin.BundleAnalyzerPlugin()
    ],
}

模式(mode)

通过设置 mode 参数为 development、production 或 none,你可以启用 webpack 在不同环境下的内置优化。mode 参数的默认值是 production。

  1. development:适用于开发环境,启用快速编译和友好错误提示等功能,但不会进行代码压缩等生产环境优化。

  2. production:适用于生产环境,默认启用代码压缩、树摇(去除未使用的代码)等优化措施,以减小打包后的文件体积。

  3. none:不启用任何优化,适用于需要完全控制构建过程的情况。

module.exports = {
  mode: 'production',
};

有了上面的基础概念,接下来让我们一起来实战配置一波webpack

webpack配置实战

在根目录下新键一个webpack.config.js文件

const path = require("path");
module.exports = {
    mode: "development",
    entry: "./src/index.js",
    output: {
        filename: "dist.js",
        path: path.resolve(__dirname,"dist"),
    }
}

其中

  • mode,选择了开发者模式

  • entry,选择了相对于config文件的src目录下的index.js作为入口文件

  • output, 对于输出配置了输出的名字,并且使用了自带的path配置了输出目录

执行npx webpack,可以看到不仅重新输出了dist.js,其中的内容也和之前的有了不一样

在上一次的打包中我们可以看到日志有以下警告:

image.png 说明我们没有设置开发的环境,这里我们就暂且给他设为开发环境。

const path = require('path');
module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: 'dist.js',
        path: path.resolve(__dirname, 'dist')
    },
}

其中

  • mode,选择了开发者模式
  • entry,选择了相对于config文件的src目录下的index.js作为入口文件
  • output, 对于输出配置了输出的名字,并且使用了自带的path配置了输出目录

执行npx webpack,可以看到不仅重新输出了dist.js,其中的内容也和之前的有了不一样

image.png 可以发现该dist.js文件中多了许多配置代码,如下图:

image.png

使用webpack插件自动生成html文件

还是安装

npm add html-webpack-plugin --dev

然后导入webpack.config.js文件

const HtmlWebpackPlugin = require("html-webpack-plugin")

再进行配置即可

  plugins:[
    new HtmlWebpackPlugin()
  ],

所以这时候再执行打包命令,可以看到输出文件夹下还多了一个index.html

这个HTML的标题默认为Webpack App

我们也可以对这个进行配置,例如:

 plugins: [new HtmlWebpackPlugin({
        title: '列表'
    })

这时我们可以看到,HTML的标题发生了变化。

image.png

配置loader兼容低版本浏览器

要让新的JavaScript的特性兼容低版本的浏览器,需要用到babel,而webpack也支持相应的loader

首先还是安装npm add --dev babel-loader @babel/core @babel/preset-env

这三个包提供了我们需要的功能

然后再进行下面的配置

{
  test: /\.js$/,
  exclude: /node_modules/,
  use: {
    loader: "babel-loader",
    options: {
      presets: ["@babel/preset-env"],
    },
  },
},

压缩打包后的js代码

分两步:

  1. 先安装依赖 npm add --dev terser-webpack-plugin

  2. 然后引入和配置 const TerserPlugin = require("terser-webpack-plugin")

optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
  },

执行 npx webpack命令打包后,我们可以发现打包后的js代码都进行了压缩,例如:删掉多余的空白行与空格

image.png

无需执行命令自动打包

现在每次修改了代码后都得重新执行打包命令

webpack也提供了一个插件能在保存后自动打包

先安装npm add --dev webpack-dev-server

在webpack.config.js中进行配置

  devServer: {
    static: "./dist",
  },

在package.json中进行配置

  "scripts": {
    "start": "webpack serve --open"
  },

这样在我们执行npm start的时候就会自动执行webpack serve

并且通过 npm start 打开的网页能在我们修改保存后自动刷新页面

避免浏览器缓存js文件

由于现在每次生成的文件名都是dist.js,所以浏览器会对这个文件进行缓存,进而不更新

为了避免进行缓存,可以给文件名添加一段随机的字符,每次更新后都生成新的随机字符

所以在webpack.config.js中配置输出即可

output: {
    filename: "[name].[contenthash].js",
    path: path.resolve(__dirname, "dist"),
  },

配置可视化打包工具

这是一个帮助分析的工具,它会可视化地展现打包过程中哪个文件占的体积比较大

同样的,先是安装这个插件npm add --dev webpack-bundle-analyzer

接着在配置中引入这个插件const BundleAnalyzerPlugin = require("webpack-bundle-analyzer");

以及在plugins中添加它

  plugins: [
    new HtmlWebpackPlugin({
      title: "test",
    }),
    new BundleAnalyzerPlugin.BundleAnalyzerPlugin()
  ],

此时再次执行npx webpack指令,将会弹出一个可视化的页面来给我们展示当前项目文件占比以及体积大小

image.png

总结

本文用到的代码地址: 代码地址

本篇文章到此就结束了,希望这篇文章能让你对入门webpack有所帮助,如果您感觉有所帮助的话,还请麻烦点赞、收藏、关注支持一波。

image.png