发布时间:2023-05-03 文章分类:WEB开发, 电脑百科 投稿人:李佳 字号: 默认 | | 超大 打印

写在最前:实际开发中需要自己配置webpack吗?

答案:不需要!

  • 实际开发中会使用命令行工具(俗称CLI一键生成带有webpack的项目
  • 开箱即用,所有webpack的配置项都是现成的!
  • 我们只需要知道webpack中的基本概念即可!

以下的学习为了更深刻了解其原理,明白其过程。有助于更好的完成项目的打包,因此也尤为重要!

由于前端开发发展迅速,各种包工具版本不断升级,出现各种兼容性问题,优先建议使用本文中所提及的版本学习,了解原理!

一、前端工程化

1. 现代化前端编程

        模块化(js的模块化、CSS的模块化、资源的模块化)

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

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

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

2. 前端工程化

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

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

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

3. 前端工程化的解决方案

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

        webpack 

        parcel 

二、webpack的基本使用

1.什么是webpack

概念:webpack 是前端项目工程化的具体解决方案

主要功能:它提供了友好的前端模块化开发支持,以及代码压缩混淆,处理浏览器端JavaScript的兼容性、性能优化等强大的功能。

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

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

2.创建列表隔行变色项目

注意,以下操作需要安装node.js

官网网址Node.js

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

一、index.html代码

<!DOCTYPE html>
<html lang="zh">
<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>Document</title>
	<script type="text/javascript" src="index.js"></script>
</head>
<body>
	<ul>
		<li>1</li>
		<li>2</li>
		<li>3</li>
		<li>4</li>
		<li>5</li>
		<li>6</li>
		<li>7</li>
		<li>8</li>
	</ul>
</body>
</html>

二、index.js代码

import $ from "jquery";
$(function(){
	$('li:odd').css('background-color','yellow')
	$('li:even').css('background-color','red')
})

最终发现,网页并没有产生应用的效果,并且报错,所以我们希望借助webpack来让浏览器读懂我们的代码。

        S 的意思是 告诉npm将包安装到 dependencies

        -S 是 --save 的简写

3.在项目中安装webpack 

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

        -D 的意思是 告诉npm将包安装到 devDependencies

        -D 是 --save-dev 的简写

  • dependencies 程序正常运行需要的包
  • devDependencies 是开发需要的包 

        信息保存在package.json文件中

        更多包详情信息可以通过 npm官网 或 npm中文文档 查询学习。

4.在项目中配置 webpack 

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

module.exports = {
    mode: 'development'
    // mode 代表webpack运行的模式,可选值 development 和 production
    //development 开发环境(不压缩,打包速度快,体积大)
    //production 生产环境(压缩,打包速度慢,体积小,进行性能优化)
}

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

"script": {
    "dev": "webpack"
    // script 节点下的脚本,可以通过npm run 执行
    // 例如: npm run dev
}

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

npm run dev

4.1 webpack.config.js 文件的作用

        webpack.config.js 是 webpack的配置文件。

        webpack在真正开始打包构建之前,会先读取这个配置文件,从而基于给定的配置,对项目进行打包。

4.2 webpack 中的默认约定

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

  1. 默认的打包入口文件为 src -> index.js
  2. 默认的输出文件路径为 dist -> main.js

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

4.3 自定义打包的入口与出口

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

const path = require('path') //导入node.js 中专门操作路径的模块
module.exports = {
    entry: path.join(__dirname,'./src/index.js'), //打包入口文件的路径 __dirname代表当前文件的存放路径
    output: {
        path: path.join(__dirname,'./dist'), //输出文件的存放路径
        filename: 'bundle.js' //输出文件的名称
    }
}

5. webpack插件

通过安装和配置第三方的插件,可以拓展webpack的能力,从而使webpack用起来更方便。

  1. webpack-dev-server

    • 类似于node.js阶段用到的nodemon工具
    • 每当修改了源代码,webpack会自动进行项目的打包和构建
  2. html-webpack-plugin

    • webpack中的 HTML 插件 (类似于一个模板引擎插件)
    • 可以通过此插件自定制index.html页面的内容

5.1安装webpack-dev-server 

npm install webpack-dev-server@3.11.2 -D

5.2配置webpack-dev-server

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

"scripts": {
    "dev": "webpack serve"
    // script 节点下的脚本,可以通过npm run 执行
    // 注意是 serve 不是 server
}

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

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

注意:

  1. webpack-dev-server 会启动一个实时打包的http服务器
  2. man.js 是在根目录的内存之下
  3. 引用直接 /man.js 即可

5.3安装html-webpack-plugin 

本处作用:将src目录下的index.html文件自动复制在根目录下。

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

npm install html-webpack-plugin@5.3.2 -D

配置 webpack.config.js 文件

// 1.导入 HTML 插件,得到一个构造函数
const HtmlPlugin = require('html-webpack-plugin')
// 2. 创建 HTML 插件的实例对象
const htmlPlugin = new HtmlPlugin({
    template: './src/index.html', // 指定源文件的存放路径
    filename: './index.html', // 指定生成的文件的存放路径
})
module.exports = {
    mode: 'development',
    plugins: [htmlPlugin], // 3. 通过 plugin 节点, 使 htmlPlugin 插件生效 
}

注意⚠️

(1)通过HTML插件复制到项目根目录中的index.html页面,也被放到了内存中

(2)HTML插件在生成的index.html页面,自动注入了打包的bundle.js文件(即不需要手动在HTML文件里引入bundle.js)

5.4.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.config.js 配置文件,或修改了package.json配置文件时,必须重启实时打包的服务器,否则最新的配置文件无法生效!

6.loader概述 

6.1loader 概述

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

而其它非.js后缀名的模块,webpack默认处理不了,需要调用loader加载器才可以正常打包,否则会报错!

loader加载器的作用:协助webpack打包处理特定的文件模块。比如:

Vue基础--webpack介绍以及基础配置 6.2 打包处理css文件

 1.运行如下命令,安装处理css文件的loader

npm i style-loader css-loader -D

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

module: { // 所有第三方文件模块的匹配规则
    rules: [ //文件后缀名的匹配规则
        {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader'
            ]
        }
    ]
}

注意⚠️

  • 其中 test 表示匹配的文件类型,use表示对应要调用的loader
  • use数组中指定的loader顺序是固定的、多个loader的调用顺序是: 从后往前调用
  • module和 mode 、entry、output、plugins、devServer平级 

6.3打包处理less文件 

1.运行如下命令,安装处理less文件loader

npm i less-loader less -D

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

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

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

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

使用相对路径和base24路径都能显示相同的小图片。

使用base24可以防止浏览器发起不必要的请求(标签一次请求,logo.jpg又是一次请求),缺点是会稍微增加体积。

1.运行如下命令,安装处理url路径相关文件的loader 

npm i url-loader file-loader -D

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

module: {
    rules: [
        {
            test: /\.jpg|png|gif$/,
            use: 'url-loader?limit=22229'
        }
    ]
}

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

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

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

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

例如webpack无法处理下面的js代码:

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

6.6安装babel-loader相关的包 

1.运行如下的命令安装对应的依赖包

npm i babel-loader @babel/core @babel/plugin-proposal-decorators -D

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

module: {
    rules: [
        {
            test: /\.js$/,
            use: 'babel-loader',
            exclude: /node_modules/
            //在配置 babel-loader 的时候,程序员只需要把自己的代码进行转换即可;
            //一定要排除 node_modules 目录中的 JS 文件
        }
    ]
}

6.7配置babel-loader

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

module.exports = {
    //声明babel可用的插件
    plugins: [            //在plusgins节点下
        [
            '@babel/plugin-proposal-decorators',
            {
                legacy:true
            }
        ]
    ]
}

该插件官方文档,详细内容学习请跳转 babel/plugin-proposal-decorators · Babel 

7.打包发布

7.1为什么要打包发布

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

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

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

7.2配置webpack的打包发布 

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

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

--model 是一个参数项,用来指定webpack的运行模式

production代表生产环境,会对打包生成的文件进行代码压缩性能优化

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

注意⚠️

dist文件夹是打包后即时生成的,可以删去重新打包

(应该说修改webpack配置后重新打包前必须要删,运行再重新生成,这样会很麻烦,下面会解决这个问题) 

8.优化图片和js文件的存放路径 

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

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

output: {
    path: path.join(__dirname,'dist'),
    //明确告诉webpack 把生成的main.js 文件存放到 dist目录下的 js子目录中
    filename: 'js/main.js',
}

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

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

//1 (注意,此方法不推荐)
{
    test: /\.jpg|png|gif$/,
    use: {
        loader: 'url-loader',
        options: {
            limit: 22228,
            // 明确指定把打包生成的图片文件,存放到 dist 目录下的 image目录中
            outputPath: 'image'
        },
    },
}
//2 (推荐此方法)
module: {
    rules: [
      // 处理图片文件的 loader
      // 如果需要调用的 loader 只有一个,则只传递一个字符串也行,如果有多个loader,则必须指定数组
      // 在配置 url-loader 的时候,多个参数之间,使用 & 符号进行分隔
      { 
        test: /\.jpg|png|gif$/, 
        use: 'url-loader?limit=470&outputPath=images' 
      }    
    ]
  },

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

为了在每次打包发布时自动清理掉dist目录下的旧文件

可以安装并配置clean-webpack-plugin插件:

安装命令如下:

npm i clean-webpack-plugin -D

 配置参数:

const { CleanWebpackPlugin} = require('clean-webpack-plugin')
const cleanPlugin = new CleanWebpackPlugin()
plugins:[htmlPlugin,cleanPlugin] 
//此处有两个插件
//htmlPlugin为上面讲src的html放入根目录的插件
//cleanPlugin为清理dist文件的插件

插件详细请跳转学习:clean-webpack-plugin - npm search (npmjs.com)

9.Source Map

9.1什么是Source Map

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

简单理解:浏览器报错提示的代码行和实际代码行不一定对应,现在需要想办法帮助定位代码出错行。

9.3解决默认Source Map的问题

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

module.exports = {
    mode: ‘development’,
    //在开发调试阶段,建议大家都把devtool设置为 eval-source-map
    devtool: 'eval-source-map'
}

注意⚠️:

在发布的时候,为了代码的安全性,需要注释devtool: 'eval-source-map'

关闭后,报错只定位到行数,不暴露源码

9.4Source Map的最佳使用 

  1. 开发环境下:

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

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

10. @ 设置源目录地址配置

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

但在使用前需要配置 webpack.config.js

resolve: {
    alias: {
        //告诉webpack, @ 符号表示 src目录
        '@': path.join(__dirname,'./src/')
    }
}

resolve和mode、entry、output、plugins、devServer平级 

配置完成后,便可以使用 @ 表示源代码目录。

import './css/index.css'
import './css/index.less'
import './js/test/info.js'
可以换成
import '@/css/index.css'
import '@/css/index.less'
import '@/js/test/info.js'

此章所有配置 webpack.config.js 文件代码展示:

const path = require('path')
// 1. 导入 html-webpack-plugin 这个插件,得到插件的构造函数
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 构造函数,创建插件的实例对象
const htmlPlugin = new HtmlPlugin({
  // 指定要复制哪个页面
  template: './src/index.html',
  // 指定复制出来的文件名和存放路径
  filename: './index.html'
})
// 注意:左侧的 { } 是解构赋值
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
// 使用 Node.js 中的导出语法,向外导出一个 webpack 的配置对象
module.exports = {
  // 在开发调试阶段,建议大家都把 devtool 的值设置为 eval-source-map
  // devtool: 'eval-source-map',
  // 在实际发布的时候,建议大家把 devtool 的值设置为 nosources-source-map 或直接关闭 SourceMap
  devtool: 'nosources-source-map',
  // mode 代表 webpack 运行的模式,可选值有两个 development 和 production
  // 结论:开发时候一定要用 development,因为追求的是打包的速度,而不是体积;
  // 反过来,发布上线的时候一定能要用 production,因为上线追求的是体积小,而不是打包速度快!
  mode: 'development',
  // entry: '指定要处理哪个文件'
  entry: path.join(__dirname, './src/index1.js'),
  // 指定生成的文件要存放到哪里
  output: {
    // 存放的目录
    path: path.join(__dirname, 'dist'),
    // 生成的文件名
    filename: 'js/bundle.js'
  },
  // 3. 插件的数组,将来 webpack 在运行时,会加载并调用这些插件
  plugins: [htmlPlugin, new CleanWebpackPlugin()],
  devServer: {
    // 首次打包成功后,自动打开浏览器
    open: true,
    // 在 http 协议中,如果端口号是 80,则可以被省略
    port: 80,
    // 指定运行的主机地址
    host: '127.0.0.1'
  },
  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-loader 的时候,多个参数之间,使用 & 符号进行分隔
      { test: /\.jpg|png|gif$/, use: 'url-loader?limit=470&outputPath=images' },
      // 使用 babel-loader 处理高级的 JS 语法
      // 在配置 babel-loader 的时候,程序员只需要把自己的代码进行转换即可;一定要排除 node_modules 目录中的 JS 文件
      // 因为第三方包中的 JS 兼容性,不需要程序员关心
      { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
    ]
  },
  resolve: {
    alias: {
      // 告诉 webpack,程序员写的代码中,@ 符号表示 src 这一层目录
      '@': path.join(__dirname, './src/')
    }
  }
}