前端工程化:Webpack之常见配置详解

2022-02-02 21:57:14 浏览数 (1)

一、前言

相信很多人在学习前端过程中,都接触过webpack。但可能在创建前端项目时,都只是用脚手架vue-cli的初始化命令跑一下,将webpack当成一个黑盒使用,刚开始我也是这样,但是虽然一切配置都能通过脚手架自动完成,我们不用学会如何手动去配置,但是我们也至少应该知道,webpack每条配置的作用

今天,我就在这里分享一下——webpack常见配置及其作用

以下部分图片资源来源于网络,如有侵权,请联系我删除!

在介绍webpack之前,我们先来了解一下什么是前端工程化,从而引入webpack产生的原因

大家可能会以为前端开发仅仅只是

⚫掌握HTML、CSS、JS

⚫能够使用JQuery操作DOM并发起ajax请求

⚫在美化页面样式时,导入bootstrap

⚫实现网页布局时,导入Layui

二、前端工程化

概念

在企业级的前端项目开发中,把前端开发所需的工具、技术、流程、经验等进行规范化标准化。

具体遵循以下四个“现代化”准则

⚫ 模块化(js 的模块化、css 的模块化、资源的模块化)

⚫ 组件化(复用现有的 UI 结构、样式、行为)

⚫ 规范化(目录结构的划分、编码规范化、接口规范化、文档规范化、 Git 分支管理)

⚫ 自动化(自动化构建、自动部署、自动化测试)

  • 模块化:对 js、css的功能,对静态资源的类型模块化拆分,比如当你用node写接口时,单独把api接口的相关代码抽出来写在一个js文件里
  • 组件化:如bootstrap、layui提供的按钮、导航栏等,都是可以直接拿来复用的组件
  • 规范化:在构建目录结构、编写代码、接口等所要遵循的一些规则
  • 自动化:像热部署、通过git自动发布我们新改动创建的代码等

如果做不到上述这四个“现代化”,那我们平时感觉在写的项目,其实都只是demo。

那么我们在开发时,有没有什么工具能帮助我们做到前端工程化呢?

三、webpack

1、官方概念:

webpack是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)

实际上,它是目前主流的前端工程化的解决方案。

2、功能:

提供了友好的前端模块化开发支持,以及代码压缩混淆、处理不同浏览器端 JavaScript 的兼容性

能优化等强大的功能。

代码压缩能够提高我们程序的运行速度;

解决了兼容性问题,我们就能没有后顾之忧的在项目中写js的高级代码(如ES6)。

这就能让我们开发时只用把重心放到具体功能的实现上,提高了前端开发效率项目的可维护性。

3、webpack的安装(需要在npm包管理器环境)

新建项目空白目录,并运行 npm init –y 命令,初始化包管理配置文件 package.json

新建 src 源代码目录

新建 src -> index.html 首页和 src -> index.js 脚本文件

在项目根目录终端运行如下的命令,安装 webpack 相关的两个包:

npm install webpack@5.42.1 webpack-cli@4.7.2 -D

4、常用配置和基本使用

4.1 在项目中配置 webpack

① 在项目根目录中,创建名为 webpack.config.js 的 webpack 配置文件,并初始化如下的基本配置:

代码语言:javascript复制
// 使用 Node.js 中的导出语法,向外导出一个 webpack 的配置对象
module.exports = {
  mode: 'development' //mode 用来指定构建模式。可选有development和production
}

webpack.config.js 是 webpack 的配置文件。webpack 在开始打包构建之前,会先读取这个配置文件

并基于我们在配置文件中给定的配置,对项目进行打包,并生成dist文件夹,存储打包后的项目文件。

注意:由于 webpack 是基于 node.js 开发出来的打包工具,因此在它的配置文件中,支持使用 node.js 相关

的语法和模块进行 webpack 的个性化配置。

② 在 package.jsonscripts 节点下,新增 dev 脚本如下:

代码语言:javascript复制
"scripts": {
    "dev": "webpack",//scripts下的脚本可以通过npm run运行,如npm run dev,实际上是执行npm run webpack serve
    "build": "webpack --mode production"
  },

③ 在终端中运行 npm run dev 命令,启动 webpack 进行项目的打包构建

4.2 mode 的可选值

mode 节点的可选值有两个,分别是:

development

⚫ 开发环境

⚫ 不会对打包生成的文件进行代码压缩和性能优化

打包速度快,适合在开发阶段使用

production

⚫ 生产环境

⚫ 会对打包生成的文件进行代码压缩和性能优化

打包速度很慢,仅适合在项目发布阶段使用

4.3 webpack 中的默认约定

在 webpack 4.x 和 5.x 的版本中,有如下的默认约定:

① 默认的打包入口文件为 src -> index.js

② 默认的输出文件路径为 dist -> main.js

注意:可以在 webpack.config.js 中修改打包的默认约定

因此,在运行npm run dev后,系统会默认将src -> index.js文件,打包输出到dis -> main.js

疑问:那项目中其他的文件如css、less、jpg文件怎么被打包输出呢?(提前预告下文的loader知识点)

回答:webpack只能解析.js文件,这些类型文件需要对应的loader加载器来解析并打包,生成文件的路径可以自己配置

下面, 我们在 webpack.config.js 配置文件中,通过 entry 节点指定打包的入口。通过 output 节点指定打包的出口。

代码语言:javascript复制
// entry: '指定要处理哪个文件'
  entry: path.join(__dirname, './src/index.js'),
  // 指定生成的文件要存放到哪里
  output: {
    // 存放的目录
    path: path.join(__dirname, 'dist'),
    // 生成的文件名
    filename: 'js/bundle.js'
  },

这样就能让系统将src->index.js,打包输出到dis -> js -> bundle.js

另外,应在 src文件夹下的 index.html 源代码中导入 dist 文件下的打包好的js文件,打包后的bundle.js文件会解析转换index.js文件下的内容,使得任何版本的浏览器都能兼容。

(先别动手,使用下面的webpack-dev-server插件后,就不用导入了)

代码语言:javascript复制
<script src="../dist/bundle.js"></script>

痛点:但是,这也导致了我们每次对 index.js 文件进行修改,都需要npm run dev,来更新bundle.js文件内容。

五、webpack插件的使用

① webpack-dev-server

⚫ 类似于 node.js 阶段用到的 nodemon 工具

⚫ 每当修改了源代码,webpack 会自动进行项目的打包和构建

webpack-dev-server 可以让 webpack 监听项目源代码的变化,从而进行自动打包构建

安装

代码语言:javascript复制
npm install webpack-dev-server@3.11.2 -D

配置

修改 package.json -> scripts 中的 dev 命令如下:

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

② 再次运行 npm run dev 命令,重新进行项目的打包

③ 在浏览器中访问 http://localhost:8080 地址,查看自动打包效果

此时,运行命令后,每次修改源代码,都会在内存自动构建生成新的bundle.js文件,进行实时打包

但是运行命令后,webpack-dev-server 会启动一个实时打包的 http 服务器 http://localhost:8080,打开网址后,会呈现我们项目的根目录结构(下面会说明如何配置更改网址)

点开src,便自动展现了index.html页面(系统会默认打开index.html文件),我们对源代码的任何更改效果都会呈现在上面。

而打包实时生成的bundle.js,保存在我们电脑的内存当中,可以通过http://localhost:8080/bundle.js来访问。

① 不配置 webpack-dev-server 的情况下,webpack 打包生成的bundle.js文件,会存放到实际的物理磁盘

⚫ 严格遵守开发者在 webpack.config.js 中指定配置

⚫ 根据 output 节点指定路径进行存放

② 配置了 webpack-dev-server 之后,打包生成的bundle.js文件存放到了内存

⚫ 不再根据 output 节点指定的路径,存放到实际的物理磁盘上

⚫ 提高了实时打包输出的性能,因为内存比物理磁盘速度快很多

我们index.html的源代码页面上,也会隐式导入生成在内存的bundle.js文件。

代码语言:javascript复制
<script src="/bundle.js"></script>//源代码页面上看不到,但是在网页上用"检查"可以看到

痛点: 打开http://localhost:8080后不能直接展现我们index.js页面效果, 必须要点开src才行

疑问: 如何修改http服务器地址?

解决:

1、使用html-webpack-plugin插件来复制index.html文件到项目根目录

2、配置devServer属性

② html-webpack-plugin

⚫ webpack 中的 HTML 插件(类似于一个模板引擎插件

⚫ 可以通过此插件自定制 index.html 页面的内容

思路通过 html-webpack-plugin 插件,将 src 目录下的 index.html 首页,复制一份到项目根目录中

安装:

代码语言:javascript复制
npm install html-webpack-plugin@5.3.2 -D

配置:

在webpack.config.js文件中配置 html-webpack-plugin插件 和 devServer属性

代码语言:javascript复制
// 1. 导入 html-webpack-plugin 这个插件,得到插件的构造函数
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 构造函数,创建插件的实例对象
const htmlPlugin = new HtmlPlugin({
  // 指定要复制哪个页面
  template: './src/index.html',
  // 指定复制出来的文件名和存放路径
  filename: './index.html'//存放在内存中
})

module.exports = {
plugins: [htmlPlugin],
  devServer: {
    // 首次打包成功后,自动打开浏览器
    open: true,
    // 在 http 协议中,如果端口号是 80,则可以被省略
    port: 80,
    // 指定运行的主机地址
    host: '127.0.0.1'
  },
}

此时, 运行服务器后, 服务器网址会自动打开,呈现index.html页面效果

注意: 复制的index.html文件存放在内存中, 且与源文件不是同一个文件, 复制的index.html生成后, 系统也会自动给它注入内存中实时构建的bundle.js文件

六、loader加载器

1、概述:

在实际开发过程中,webpack 默认只能打包处理以 .js 后缀名结尾的模块。其他非 .js 后缀名结尾的模块,

webpack 默认处理不了,需要调用 loader 加载器才可以正常打包,否则会报错!

2、作用

协助 webpack 打包处理特定的文件模块

比如:

⚫ css-loader 可以打包处理 .css 相关的文件

⚫ less-loader 可以打包处理 .less 相关的文件

⚫ babel-loader 可以打包处理 webpack 无法处理的高级 JS 语法

3、配置使用

下面挂一下loader加载器的工作流程图

4、常见配置代码:

代码语言:javascript复制
module: {
    rules: [
      // 定义了不同模块对应的 loader

      { test: /.css$/, use: ['style-loader', 'css-loader'] },

      // 处理 .less 文件的 loader
      { test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },

      // 处理图片文件的 loader
      // 如果需要调用的 loader 只有一个,则只传递一个字符串也行,如果有多个loader,则必须指定数组

      // 打包处理样式表中与 url 路径相关的文件
      // 需要预先安装模块 npm i url-loader@4.1.1 file-loader@6.2.0 -D
      // 在配置 url-loader 的时候,多个参数之间,使用 & 符号进行分隔
      { test: /.jpg|png|gif$/, use: 'url-loader?limit=470&outputPath=images' },

      // 使用 babel-loader 处理高级的 JS 语法
      // 在配置 babel-loader 的时候,一定要排除 node_modules 目录中的 JS 文件
      { test: /.js$/, use: 'babel-loader', exclude: /node_modules/ }
    ]
  },

5、babel-loader

webpack 只能打包处理一部分高级的 JavaScript 语法。对于那些 webpack 无法处理的高级 js 语法,需要借

助于 babel-loader 进行打包处理

安装

代码语言:javascript复制
npm i babel-loader@8.2.2 @babel/core@7.14.6 @babel/plugin-proposal-decorators@7.14.5 -D

配置

在项目根目录下,创建名为 babel.config.js 的配置文件,定义 Babel 的配置项如下:

代码语言:javascript复制
module.exports = {
  // 声明 babel 可用的插件
  // 将来,webpack 在调用 babel-loader 的时候,会先加载 plugins 插件来使用
  plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]]
}

在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

代码语言:javascript复制
module: {
    rules: [
      { test: /.js$/, use: 'babel-loader', exclude: /node_modules/ }
    ]
  },

七、打包发布

1. 为什么要打包发布

项目开发完成之后,需要使用 webpack 对项目进行打包发布,主要原因有以下两点:

① 开发环境下,打包生成的文件存放于内存中,无法获取到最终打包生成的文件

② 开发环境下,打包生成的文件不会进行代码压缩和性能优化

为了让项目能够在生产环境中高性能的运行,因此需要对项目进行打包发布。

2. 配置 webpack 的打包发布

在 package.json 文件的 scripts 节点下,新增 build 命令如下:

代码语言:javascript复制
"scripts": {
    "dev": "webpack serve",
    "build": "webpack --mode production"
  },

--model 是一个参数项,用来指定 webpack 的运行模式。production 代表生产环境,会对打包生成的文件

进行代码压缩和性能优化。

注意:通过 --model 指定的参数项,会覆盖 webpack.config.js 中的 model 选项。

3. 打包后生成的dist文件夹结构配置

我们的项目中包含图片资源、js文件、css文件等等类型,我们需要进行配置,告诉系统每种类型文件的生成路径。

把 JavaScript 文件统一生成到 js 目录中

在 webpack.config.js 配置文件的 output 节点中,进行如下的配置:

把图片文件统一生成到 image 目录中

修改 webpack.config.js 中的 url-loader 配置项,新增 outputPath 选项即可指定图片文件的输出路径:

5. 自动清理 dist 目录下的旧文件

为了在每次打包发布时自动清理掉 dist 目录中的旧文件,可以安装并在webpack.config.js文件中配置 clean-webpack-plugin 插件:

八、Source Map

概念:

Source Map 就是一个信息文件,里面储存着代码的位置信息。也就是说,Source Map 文件中存储着压缩混淆后的代码,所对应的转换前的位置

有了它,出错的时候,除错工具将直接显示原始代码所在位置,而不是转换后的代码位置,能够极大的方便后期的调试

原始代码大赏:

⚫ 变量被替换成没有任何语义的名称

⚫ 空行和注释被剔除

如何除错?Source Map!

开发环境下

在开发环境下,webpack 默认启用了 Source Map 功能。当程序运行出错时,可以直接在控制台提示错误行

的位置,并定位到具体的源代码。

问题:开发环境下默认生成的 Source Map,记录的是生成后的代码的位置。会导致运行时报错的行数与源代码的行数不一致的问题。示意图如下:

解决:在 webpack.config.js 中添加如下的配置

生成环境下

如果生产环境下,使用Source Map,不可排除不法分子会利用它来“借鉴”你的源码。

此时可以将 devtool 的值设置为 nosources-source-map。实际效果如图所示:

因此,对于Source Map

① 开发环境下:

⚫ 建议把 devtool 的值设置为 eval-source-map

⚫ 好处:可以精准定位到具体的错误行

② 生产环境下:

⚫ 建议关闭 Source Map 或将 devtool 的值设置为 nosources-source-map

⚫ 好处:防止源码泄露,提高网站的安全性

九、总结

认真看完后,是不是对常用的配置和插件的概念和作用有了大致的了解呢?我在下面给你们总结了本篇文章的主要内容:

webpack 的基本使用

⚫ 安装、webpack.config.js、修改打包入口

plugin 的基本使用

⚫ webpack-dev-server、html-webpack-plugin

loader 的基本使用

⚫ loader 的作用、loader 的调用过程

Source Map 的作用

⚫ 精准定位到错误行并显示对应的源码

⚫ 方便开发者调试源码中的错误

如果上述分享有不妥之处,欢迎大家在评论区斧正

0 人点赞