Webpack模块打包器

2021-01-27 15:34:49 浏览数 (1)

本篇博客仅适用未了解过或者没入门过 webpack 的小伙伴作为入门级的了解。

介绍

webpack是一个现代的JavaScript应用的静态模块打包工具。

随着 SPA 单页应用的发展,使用的 js/css/png 等静态资源较多且难以管理,文件夹结构也容易混乱。很多时候我们希望项目可以具备压缩css,js 正确地处理各种 js/css 的 import 以及相关的模板 html 文件。 webpack 的出现就解决了这个难题。

在官网首页就有这样一张图,bundle your assets

本质上,webpack 是一个用于现代 JavaScript 应用程序的_静态模块打包工具_。当 webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle

安装

全局安装

代码语言:javascript复制
npm install webpack -g

安装完可以用命令行 webpack -h 查看。

单独安装

通常我们会将 Webpack 安装到项目的依赖中,这样就可以使用项目本地版本的 Webpack。

代码语言:javascript复制
# 进入项目目录
# 确定已经有 package.json,没有就通过 npm init 创建
npm init
# 安装 webpack 依赖
npm install webpack --save-dev

核心概念

在开始前你需要先理解一些__核心概念__:

  • 入口(entry)
  • 输出(output)
  • loader
  • 插件(plugin)
  • 模式(mode)
  • 浏览器兼容性(browser compatibility)
  • 环境(environment)

一个非常重要的知识:

webpack 开箱即用,可以无需使用任何配置文件。然而,webpack 会假定项目的入口起点为 src/index.js,然后会在 dist/main.js 输出结果,并且在生产环境开启压缩和优化。通常你的项目还需要继续扩展此能力,为此你可以在项目根目录下创建一个 webpack.config.js 文件,然后 webpack 会自动使用它。

还有一个快速生成符合项目要求的 webpack 配置文件的方法,在使用 webpack-cli 的 init 命令时,会在创建配置文件之前会询问你几个问题。

代码语言:javascript复制
npx webpack-cli init

入口(entry)

__入口起点(entry point)__指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。 默认值是 ./src/index.js,但你可以通过在 webpack configuration 中配置 entry 属性,来指定一个(或多个)不同的入口起点。

基本的单入口写法

webpack.config.js

代码语言:javascript复制
module.exports = {
  entry: './path/to/my/entry/file.js'
};

多入口甚至分离式写法,参考官方文档。

输出(output)

output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。 你可以通过在配置中指定一个 output 字段,来配置这些处理过程。

webpack.config.js

代码语言:javascript复制
const path = require("path")

const config = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, "dist")
  }
}
module.exports = config

loader

loader 用于对模块的源代码进行转换。loader 可以使你在 import 或 "load(加载)" 模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的得力方式。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript 或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件

例如,你可以使用 loader 告诉 webpack 加载 CSS 文件,首先安装相对应的 loader:

代码语言:javascript复制
npm install --save-dev css-loader 

然后指示 webpack 对每个 .css 使用 css-loader

webpack.config.js

代码语言:javascript复制
module.exports = {
  module: {
    rules: [
      {
        test: /.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

应保证 loader 的先后顺序:'style-loader' 在前,而 'css-loader' 在后。如果不遵守此约定,webpack 可能会抛出错误。

loader 从右到左(或从下到上)倒序执行test // 正则匹配打包过程中的文件路径use // 所用到的加载器-倒序执行

webpack 根据正则表达式,来确定应该查找哪些文件,并将其提供给指定的 loader。在这个示例中,所有以 .css 结尾的文件,都将被提供给 style-loadercss-loader

完整示例

代码语言:javascript复制
│  package-lock.json
│  package.json
│  webpack.config.js
│
├─    src
    │  index.css
    |  index.js

index.css

代码语言:javascript复制
body {
    background: #b86060;
}

index.js

代码语言:javascript复制
import './index.css'
console.log("Hello Webpack")

安装对应的loader

代码语言:javascript复制
npm install --save-dev style-loader css-loader

webpack.config.js

代码语言:javascript复制
const path = require("path")

const config = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, "dist")
  },
  module: {
    rules: [
      {
        test: /.css$/i,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
}
module.exports = config

执行打包

代码语言:javascript复制
npm run build

dist 文件夹下新建一个 index.html,引入编译后的 js 文件

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script src="./bundle.js"></script>

</body>
</html>

在浏览器中打开该文件,可以看到之前写好的 css 背景颜色就生效了。

关于loader的官方文档

关于管理资源篇的官方文档

plugin

__插件__是 webpack 的 支柱 功能。webpack 自身也是构建于你在 webpack 配置中用到的__相同的插件系统__之上!插件目的在于解决 loader 无法实现的__其他事__。由于__插件__可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入一个 new 实例。

用法

由于__插件__可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入一个 new 实例。

示例:使用html-webpack-plugin生成html模板

代码语言:javascript复制
npm install --save-dev html-webpack-plugin

webpack.config.js

HtmlWebpackPlugin 将生成一个 HTML 文件,并在其中使用 script 引入一个名为 my-first-webpack.bundle.js 的 JS 文件。

代码语言:javascript复制
const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装

const config = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, "dist")
  },
  module: {
    rules: [
      {
        test: /.css$/i,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "hello.html", // 模板html
      filename: "index.html" // 生成的html文件名
    })
  ]
}
module.exports = config

根目录/hello.html

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<h1>Hello 乐心湖</h1>
</body>
</html>

运行编译 npm run build

./dist可以看到 HtmlWebpackPlugin 就将我们的模板给整成 index.html ,并且引入了 entry-js

模式(mode)

通过选择 development, productionnone 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production

只需在配置对象中提供 mode 选项:

代码语言:javascript复制
module.exports = {
  mode: 'development'
};

支持以下字符串值:

选项

描述

development

会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development. 为模块和 chunk 启用有效的名。

production

会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin 和 TerserPlugin 。

none

不使用任何默认优化选项

如果没有设置,webpack 会给 mode 的默认值设置为 production

也就是说你可以在 js 中使用

代码语言:javascript复制
if(process.env.NODE_ENV === 'development'){
  
}

热更新

模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新所有类型的模块, 而无需完全刷新。本页面重点介绍其 实现

HMR 不适用于生产环境,这意味着它应当用于开发环境。

启用 HMR

安装

代码语言:javascript复制
npm install webpack-dev-server --save-dev

webpack.config.js

代码语言:javascript复制
devServer: {
  contentBase: './dist', // 热更新的目录
  hot: true, // 开启
},

package.json

代码语言:javascript复制
"scripts": {
  "hot": "webpack serve"
},

执行 npm run hot

在打印的日志中可以看到一个链接,默认是8080端口。

之后你修改 css html js 都会自动编译,不过有时候可能需要你手动刷新浏览器才看得到效果。


关于 Webpack 其他厉害的技巧和知识建议查看官方文档,本笔记大篇幅也是复制参考官方指南而写。


0 人点赞