美文网首页
前端工程化与Webpack详解

前端工程化与Webpack详解

作者: 扶得一人醉如苏沐晨 | 来源:发表于2023-10-30 08:56 被阅读0次

一、小白眼中的前端开发 vs 实际的前端开发

1.1. 小白眼中的前端开发

  • 会写 HTML+ CSS +JavaScript 就会前端开发
  • 需要美化页面样式,就拽一个 bootstrap 过来
  • 需要操作 DOM 或发起Ajax 请求,再拽一个jQuery 过来
  • 需要快速察现网页布局效果,就拽一个 Layui 过来

1.2. 实际的前端开发

  • 模块化(js的模块化、CSS的模块化、资源的模块化)
  • 组件化(复用现有的UI结构、样式、行为)
  • 规范化(目录结构的划分、编码规范化、接口规范化、文档规范化、Git分支管理)
  • 自动化(自动化构建、自动部署、自动化测试)

二、什么是前端工程化

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

企业中的Vue项目和React项目都是基于工程化的方式进行开发的。

优点:前端开发自成体系,有一套标准的开发方案和流程。

三、前端工程化的解决方案

3.1. 早期的前端工程化解决方案:

3.2. 目前主流的前端工程化解决方案

一、什么是webpack

官方网站🔗:webpack
概念:webpack是前端项目工程化的具体解决方案。

主要功能:提供了友好的前端模块化开发支持,以及代码压缩混淆(减小体积)、处理浏览器端JavaScript的兼容性(将高级的代码转换成低级的没有兼容问题的代码,有对应不同版本的解决方案)、性能优化等强大的功能。

优点:让程序员把工作的重心放在具体功能的实现上,提高了前端开发效率和项目的可维护性。

目前Vue, React等前端项目,基本上都是基于webpack进行工程化开发的

二、webpack的使用实践——创建列表隔行变色项目

思想-----发现问题,解决问题

2.1. 步骤

新建项目空白目录,并运行 npm init -y 命令,初始化包管理配置文件 package.json
新建src 源代码目录
新建 src->index.html首页和 src -> index.js 脚本文件
初始化首页基本的结构
运行 npm installjquery -S 命令,安装jQuery
通过 ES6模块化的方式导入jQuery,实现列表隔行变色效果

-S等价于--save

2.1.1. 目录结构如下

image.png

2.1.2. 检查jquery是否安装成功

image.png

2.1.3. index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>列表隔行变色</title>
    <script src="./index.js"></script>
  </head>

  <body>
    <ul>
      <li>这是第1个li</li>
      <li>这是第2个li</li>
      <li>这是第3个li</li>
      <li>这是第4个li</li>
      <li>这是第5个li</li>
      <li>这是第6个li</li>
      <li>这是第7个li</li>
      <li>这是第8个li</li>
      <li>这是第9个li</li>
    </ul>
  </body>
</html>

2.1.4. index.js

/*
 *index.js
 */
// 1、使用ES6导入语法,导入jquery
import $ from "jquery";

// 2、定义jquery的入口函数
$(function () {
  // 实现奇偶行变色
  $("li:odd").css("background-color", "red");
  $("li:even").css("background-color", "pink");
});

2.1.5. 打开浏览器报语法错,效果未实现

image.png

2.1.6. 此时使用webpack解决这个问题

2.1.7. 在项目中安装webpack

在终端运行如下的命令,安装 webpack 相关的两个包

npm install webpack@5.42.1
npm install webpack-cli@4.7.2 -D
image.png

可以去官方文档网站查询npm命令

🔗:npm官网

🔗:npm中文文档

2.1.8. 在项目中配置webpack

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

// 使用node.js中的导出语法,向外导出一个webpack的配置对象
module.exports = {
  // 代表webpack的运行模式,有 development 和 production
  mode: "development",
};

两种模式的区别

  • production模式(需要重新运行脚本)会把文件压缩(webpack的功能之一),体积减小,打包时间增长

  • 开发阶段使用development 追求打包速度快;发布上线阶段使用production 追求打包体积小

(2)在package.json的script节点下,新增dev脚本如下:

 "scripts": {
    "dev": "webpack",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  • script节点下的脚本,可以通过 npm run 执行,例如 npm run dev

  • 此时真正执行的命令是 "webpack"

  • 在运行webpack之前,会先读取根目录下webpack.config.js这个配置文件,拿到配置文件中向外导出的配置选项mode

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

image.png

(4)webpack在目录中生成dist文件夹,其下的main.js是index.js解决了兼容性问题后的版本

image.png

(5)index.html中引入main.js就没有兼容性问题了

<!-- <script src="./index.js"></script> -->
    <script src="../dist/main.js"></script>
image.png

三、小总结

3.1. mode的可选值

  • (1)development

开发环境
不会对打包生成的文件进行代码压缩性能优化
打包速度快,适合在开发阶段使用

  • (2)production

生产环境
对打包生成的文件进行代码压缩性能优化
打包速度很慢,仅适合在项目发布阶段使用

3.2. webpack.config.js文件的作用

是webpack的配置文件。webpack在真正开始打包构建之前,会读取这个配置文件(拿到向外导出的配置选项),从而基于给定的配置,对项目进行打包。

注意:由于webpack是基于node.js开发出来的打包工具,因此在它的配置文件中,支持使用node.js相关的语法和模块进行webpack的个性化配置。

3.3 webpack中的默认约定

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

(1)默认的入口打包文件为 src -> index.js (没有会报错)

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

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

3.4 自定义打包的入口和出口

webpack.config.js配置文件中,通过entry节点指定打包的入口。通过output节点指定打包的出口。示例代码:

const path = require("path"); //导入node.js中专门操作路径的模块

module.exports = {
  // 代表webpack的运行模式,有 development 和 production
  mode: "development",
  entry: path.join(__dirname, "./src/index.js"), //打包入口文件的路径
  output: {
    path: path.join(__dirname, "./dist"), //输出文件的存放路径
    filename: "bundle.js", //输出文件的名称
  },
};
  • __dirname代表当前文件的存放路径

  • 记得index.html中引用的js文件路径也要跟着改变

    <!-- <script src="./index.js"></script> -->
    <!-- <script src="../dist/main.js"></script> -->
    <script src="../dist/bundle.js"></script>

四、webpack中的插件

4.1. webpack插件的作用

通过安装和配置第三方的插件,可以拓展webpack的能力,从而使webpack用起来更方便。最常用的webpack插件有如下两个:

  • (1)webpack-dev-server

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

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

  • (2)html-webpack-plugin

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

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

五、安装配置使用webpack-dev-server

5.1. 安装webpack-dev-server

运行如下的命令,即可在项目中安装此插件:

npm install webpack-dev-server@3.11.2 -D

该包会进入devDependencies节点中

5.2. 配置webpack-dev-server

(1)修改package.json -> scripts 中的dev命令如下

  "scripts": {
    "dev": "webpack serve"
  },

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

笔者在重新运行的时候出现报错 “ Unable to load '@webpack-cli/serve' command”:

image.png

经分析猜测是因为上文安装的脚手架webpack-cli@4.7.2已不兼容该插件,故改为安装webpack-cli@4.9.0版本(安装最新版本的命令为 "npm install webpack-cli -D" ,即不指定版本号)

image.png

再运行npm run dev,成功

image.png

光标闪烁代表在监听代码的改动,一旦改动后保存会自动重新compile

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

看不到页面效果,因为此时project在http服务器上运行

image.png image.png

进入 src 目录,浏览器会自动展示index.html页面。此时还是未改变的页面

webpack输出文件是在根目录下的bundle.js

image.png

webpack-dev-server没有将输出文件放在物理磁盘上,而是放到了内存中,所以资源管>理器中看不到,但是可以通过路径访问到

所以index.html应该引用内存中的输出文件

<!-- <script src="../dist/bundle.js"></script> -->
    <!-- 加载和引用内存中的输出文件 -->
    <script src="/bundle.js"></script>

页面样式可以实时改变了 (以li: even的background-color改成了blue为例)

image.png

以上,文件的自动打包是由webpack+webpack-dev-server插件实现的。

但现在每次进入根目录还需要再进入src目录才能看到index.html的页面,比较麻烦。如果能复制一份index.html放到项目根目录中,就能直接打开html页面了

六、安装配置使用html-webpack-plugin

6.1. 安装html-webpack-plugin

运行如下的命令,即可在项目中安装此插件:

npm install html-webpack-plugin@5.3.2 -D

6.2. 配置html-webpack-plugin

/**
 * webpack.config.js
 */
// 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 = {
    // 代表webpack的运行模式,有 development 和 production
    mode: 'development',
    // 3、插件的数组,将来webpack运行时会加载并调用这些插件
    plugins:[htmlPlugin]
}

再 npm run dev ,进入http://localhost:8080/ 首页,就能立即看到立即看到首页

6.3. 解释html-webpack-plugin

(1)通过HTML插件复制到项目根目录中的index.html页面,也被放到了内存中
(2)HTML插件在生成的index.html页面自动注入了打包的bundle.js文件(即不需要手动在HTML文件里引入bundle.js)

七、devServer节点

在webpack.config.js配置文件中,可以通过devServer节点对webpack-dev-server插件进行更多的配置,示例代码:

/*
*webpack.config.js中的module.exporte
*/
 devServer: {
    // 初次打包完成后,自动打开浏览器
    open: true,
    // 在http协议中,如果端口号是80,可以被省略(仅显示为localhost)
    port: 80,
    // 指定运行的主机地址
    host: "127.0.0.1",
  },

八、webpack中的loader

8.1. loader概述

在实际开发中,webpack默认只能打包处理以.js后缀名结尾的模块。其他非.js后缀名结尾的模块,webpack默认处理不了,需要调用loader加载器才可以正常打包,否则会报错!

  • loader加载器的作用:协助webpack打包处理特定的文件模块。比如:
  • css-loader可以打包处理.css相关的文件
  • less-loader可以打包处理.less相关的文件
  • babel-loader可以打包处理webpack无法处理的高级js语法

8.2. loader调用的过程

image.png

8.3. 打包处理CSS文件

在src下新建css文件夹,css下新建index.css

image.png
/* index.css */

li {
  list-style: none;
}

在index.js中导入index.css

// 导入样式(在webpack中,一切皆模块都可以通过ES6导入语法进行导入和使用)
import "./css/index.css";

终端报错,提示需要安装合适的加载器处理此类文件

image.png

打包处理CSS文件的步骤:

  • 运行npm i style-loader@3.0.0 css-loader@5.2.6 -D 命令,安装处理 css 文件的loader
  • 在webpackconfig.js的 module -> rules 数组中,添加 loader 规则如下:
  module: {
    // 所有第三方文件模块的匹配规则
    rules: [
      // 文件后缀名的匹配规则
      { test: /\.css$/, use: ["style-loader", "css-loader"] }, //打包处理css文件
    ],
  },
  • 其中,test 表示匹配的文件类型,use 表示对应要调用的 loader
    注意:
  • use 数组中指定的 loader 顺序是固定的
  • 多个loader 的调用顺序是: 从后往前调用

注意module和 mode 、entry、output、plugins、devServer平级

注意style-loader和css-loader顺序不能写反,因为loader在调用的时候是从后往前调的。webpack把index.css这个自己不能处理的文件,先转交给最后一个个loader(css-loader)处理,处理完后转交给前面一个loader(style-loader),直至前面没有loader了,就转交给webpack,weebpack把结果合并到 /dist/bundle.js中,最终生成打包好的文件

重新打包npm run dev (只要修改了webpack配置文件就要重新打包)

image.png

即,当webpack发现某个文件处理不了的时候,会查找webpack.config.js这个配置文件,看module.rules数组中,是否配置了对应的loader加载器

8.4. 打包处理less文件

打包处理less文件的步骤:

  • 运行npm i less-loader@10.0.1 less@4.1.1 -D 命令,安装处理 css 文件的loader
  • 在webpackconfig.js的 module -> rules 数组中,添加 loader 规则如下:
  module: {
    // 所有第三方文件模块的匹配规则
    rules: [
      // 文件后缀名的匹配规则
      { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader"] }, //打包处理less文件
    ],
  },

安装的less是配置依赖项,即less-loader依赖的,并没有在rules中使用

在src下新建less文件夹,less下新建index.less

image.png
/* index.css */

li {
  list-style: none;
}

在index.js中导入index.less

// 导入样式(在webpack中,一切皆模块都可以通过ES6导入语法进行导入和使用)
// index.less
html,
body,
ul {
  margin: 0;
  padding: 0;
  li {
    line-height: 30px;
    padding-left: 20px;
    font-size: 12px;
  }
}

npm run dev运行项目

image.png

8.5. 打包处理样式表中与url路径相关的文件

base64小复习:
使用相对路径和base64路径都能显示相同的小图片。使用base64可以防止浏览器发起不必要的请求(标签一次请求,logo.jpg又是一次请求),缺点是会稍微增加体积。所以一般图片用base64

image.png

url-loader可以把jpg|png|gif格式的图片转化为base64

步骤

  • 运行 npm i url-loader@4.1.1 file-loader@6.2.0 -D 命令
  • 在webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
module: {
    // 所有第三方文件模块的匹配规则
    rules: [
      // 文件后缀名的匹配规则
      { test: /\.jpg|png|gif$/, use: "url-loader?limit-22229" }, //处理样式表中与url路径相关的文件
    ],
  },

其中?之后的是 loader 的参数项

  • limit 用来指定图片的大小,单位是字节 (byte)
  • 只有小于等于limit 大小的图片,才会被转为 base64 格式的图片

index.html中添加一个img标签把/src/images/logo.jpg设置给src属性

   <!-- index.html -->
    <!-- 需求:把/src/iamges/logo.jpg设置给src属性 -->
    <img src="" alt="" class="box" />
//index.js
// 1、导入图片,得到图片文件
import logo from './images/logo.jpg'
 
// 2、给img标签的src动态赋值
$('.box').attr('src', logo)

可以看到img的路径已经被转为base64

image.png

8.6. 打包处理js文件中的高级语法

webpack 只能打包处理一部分高级的JavaScript 语法。对于那些 webpack 无法处理的高级js 语法,需要借助于 babel-loader 进行打包处理。例如 webpack 无法处理下面的JavaScript 代码:

// 1.定义了名为 info 的饰器
  function info(target) {
    // 2.为目标添加静态属性
    infotarget.info = "person info";
  }
  // 3.为 Person 类应用 info 装饰器
  @info
  class Person {}
  // 4打印 Person 的静态属性 info
  console.log(Person.info);
image.png

8.6.1. 安装babel-loader相关的包

  • 运行如下的命令安装对应的依赖包
    npm i babel-loader@8.2.2 @babel/core@7.14.6 @babel/plugin-proposal-decorators@7.14.5 -D
  • 在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
module: {
    // 所有第三方文件模块的匹配规则
    rules: [
      //  注意:必须使用 exclude 指定排除项,因为 node_modules 目录下的第三方包不需要被打包
      { test: /\.js$/, use: "babel-loader", exclude: /node_modules/ },
    ],
  },

8.6.2. 配置babel-loader

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

module.exports = {
  //声明 babel 可用的插件
  plugins: [["@babel/plugin-proposal-decorators", { legacy: true }]],
};

该插件官方文档🔗:@babel/plugin-proposal-decorators · Babel (插件配置均可在官方文档查看粘贴)

九、打包发布

发布上线:前端将写好的项目文件打包(dist)发给后端,后端部署上线

现在需要解决的问题是:把页面(根目录下的index.html和bundle.js)生成到实际的物理磁盘上

9.1. 为什么要打包发布

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

  • 开发环境下,打包生成的文件存放于内存中,无法获取到最终打包生成的文件
  • 开发环境下,打包生成的文件不会进行代码压缩和性能优化

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

9.2. 配置webpack的打包发布

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

"scripts": {
    "dev": "webpack serve",
    "build": "webpack --mode production"
  },

--model 是一个参数项,用来指定 webpack 的运行模式。
production 代表生产环境,会对打包生成的文件进行代码压缩和性能优化。

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

运行 npm run build

image.png
image.png

dist文件夹是打包后即时生成的,可以删去重新打包(应该说修改webpack配置后重新打包前必须要删,运行再重新生成,这样会很麻烦,下面会解决这个问题)

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

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

 output: {
    path: path.join(__dirname, "./dist"), //输出文件的存放路径
    // 明确告诉 webpack 把生成的 bundle.js 文件存放到 dist 目录下的 js 子目录中
    filename: "js/bundle.js", //输出文件的名称
  },

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

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

//webpack.config.js中module.rules
// 在配置url-loader的时候,多个参数用&进行分隔
{ test: /\.jpg|png|gif$/, use: 'url-loader?limit=22229&outputPath=images' },

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

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

1.安装清理 dist 目录的 webpack 插件

npm install clean-webpack-plugin@3.0.0 -D

2.按需导入插件、得到插件的构造函数之后,创建插件的实例对象

const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const cleanPlugin = new CleanWebpackPlugin();

// 3.把创建的 cleanPlugin 插件实例对象,挂载到 plugins 节点中

plugins: [htmlPlugin, cleanPlugin], // 挂载插件

现在npm run build时webpack会自动先删除旧的dist再生成新的dist

9.6. 最终打包的dist文件目录结构如下

image.png

十、Source Map

10.1. 什么是Source Map

Source Map是一个信息文件,里面存储着位置信息。即Source Map存储着压缩混淆后的代码,所对应的转换前的位置。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码,能极大的方便后期的调试

eg. 控制台的报错行是bundle.js打包后的行数,要转为原始index.js的行数


image.png

10.2. webpack开发环境下的Source Map

开发环境下,webpack默认启用了Source Map功能。当程序运行出错时,可以直接在控制台提示错误行的位置,并定位到具体的源代码

10.2.1. 默认Source Map的问题

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

image.png

10.2.2. 解决默认Source Map的问题

开发环境下,推荐在 webpack.config.s 中添加如下的配置,即可保证运行时报错的行数与源代码的行数保持一致:

module.exports = {
  // 代表webpack的运行模式,有 development 和 production
  mode: "development",
  //此选项生成的 Source Map 能够保证"运行时报错的行数"与"源代码的行数”保持一致
  devtool: "eval-source-map",
};

10.3. webpack生产环境下的Source Map

在生产环境下,如果省略了devtool选项,则最终生成的文件中不包含Source Map,这能够防止源代码通过Source Map的形式暴露给别有所图之人

image.png

10.3.1. 只定位行数不暴露源码

可以将devtool的值设置为 "nosources-source-map",

module.exports = {
  // 代表webpack的运行模式,有 development 和 production
  mode: "development",
  //此选项生成的 Source Map 能够保证"运行时报错的行数"与"源代码的行数”保持一致
  devtool: "nosources-source-map",
};
image.png

10.3.2. 定位行数且暴露源码

可以将devtool的值设置为 "source-map",

module.exports = {
  // 代表webpack的运行模式,有 development 和 production
  mode: "development",
  //此选项生成的 Source Map 能够保证"运行时报错的行数"与"源代码的行数”保持一致
  devtool: "source-map",
};
image.png

10.4. Source Map的最佳实践

开发环境下:

  • 建议把 devtool的值设置为 eval-source-map
  • 好处:可以精准定位到具体的错误行

生产环境下:

  • 建议关闭 Source Map 或将 devtool 的值设置为 nosources-source-map
  • 好处:防止源码泄露,提高网站的安全性

以上,介绍了webpack的一些配置,可以看到是比较复杂容易出错的,在实际开发中往往借助命令行工具(俗称CLI)一键生成带有webpack的项目,不需要自己配置,开箱即用,所有的webpack配置项都是现成的。但以上实操并不是无用功,了解一些基础原理有助于更好地理解项目打包,以及遇到一些报错时能够知道原因。

补充:

在import导入文件的时候建议使用 @ 表示源代码目录,从外往里查找 不要使用../从里往外查找。但在使用前需要配置webpack

/**
     * webpack.config.js 与module平齐
     */
  resolve: {
    alias: {
      // 告诉webpack,程序员写的代码中,@符号表示src这一层目录
      "@": path.join(__dirname, "./src/"),
    },
  },

相关文章

  • 《前端工程化开发一》

    10分钟学会前端工程化(webpack4.0) 目录 一、概要 1.1、前端工程化 1.1.1、前端工程化的任务 ...

  • Vue2(一)

    目录 ◆ 前端工程化◆ webpack 的基本使用◆ webpack 中的插件◆ webpack 中的 loade...

  • javaweb男的gulp入手实践.gulp也能应用在jsp场景

    前言 前端圈里,现在工程化的前端已经是主流.各种前端工程化的技术比比皆是.webpack.grunt ,gulp等...

  • 25.webpack 工程师 > 前端工程师(上)

    说起前端工程化, webpack 必然在前端工具链中占有最重要的地位;说起前端工程师进阶,webpack 更是一个...

  • 九、webpack学习使用

    webpack 的基本使用 1.什么是webpack 概念:webpack 是前端项目工程化的具体解决方案。 主要...

  • 使用webpack打包前端项目

    webpack概述 随着前端体积越来越大,功能越来越丰富,这时候就需要将前端工程化,而webpack就是用于将前端...

  • webpack

    webpack是前端项目工程化的具体解决方案(打包更方便) 1. 安装webpack: npm install -...

  • webpack4 - 1.打包js

    webpack是前端工程化中的热门工具,市面上一些热门前端框架(例如React、Vue.js)使用webpack作...

  • 2020了,你需要懂的webpack知识[基础篇]

    随着前端工程化的越来越疯狂,不会点webpack的前端真的吃不香,睡不着。 所谓webpack就是一个现代 Jav...

  • webpack4系列一 打包JS

    webpack是前端工程化中的热门工具,市面上一些热门前端框架(例如React、Vue.js)使用webpack作...

网友评论

      本文标题:前端工程化与Webpack详解

      本文链接:https://www.haomeiwen.com/subject/yedkidtx.html