Webpack 完整指南

​🌈个人主页:前端青山

🔥系列专栏:Webpack篇

🔖人终将被年少不可得之物困其一生

依旧青山,本期给大家带来webpack篇专栏内容:webpack介绍

目录

介绍

一、webpack

1.1、webpack是什么

[1.2 webpack五个核心配置](#1.2 webpack五个核心配置)

[1.2.1 entry入口](#1.2.1 entry入口)

[1.2.2 output输出](#1.2.2 output输出)

[1.2.3mode 模式](#1.2.3mode 模式)

[1.2.4 loader 加载器(modules)](#1.2.4 loader 加载器(modules))

[1.2.5 plugins 插件](#1.2.5 plugins 插件)

[1.3 安装webpack](#1.3 安装webpack)

1.4webpack基本使用

[1.5 配置访问入口模板文件](#1.5 配置访问入口模板文件)

[1.6 devServer创建](#1.6 devServer创建)

[1.7 加载器](#1.7 加载器)

[1.7.1 加载器概述](#1.7.1 加载器概述)

[1.7.2 打包处理css文件](#1.7.2 打包处理css文件)

[1.7.3 打包处理scss\less\stylus文件](#1.7.3 打包处理scss\less\stylus文件)

[1.7.4 抽取单个css文件](#1.7.4 抽取单个css文件)

[1.8 图片处理](#1.8 图片处理)

[1.9 复制资源](#1.9 复制资源)

[1.10 js兼容处理](#1.10 js兼容处理)

[1.11 路径别名与导入后缀省略](#1.11 路径别名与导入后缀省略)

[1.12 tree-shaking](#1.12 tree-shaking)

[1.13 externals忽略不打入的包](#1.13 externals忽略不打入的包)

[1.14 搭建React](#1.14 搭建React)

[1.15 搭建Vue2](#1.15 搭建Vue2)

[1.16 搭建vue3](#1.16 搭建vue3)

介绍

vue脚手架 vue-cli底层就是webpack

react脚手架 create-react-app底层就是webpack

复制代码
Vite和Webpack都是现代化的前端构建工具,用于打包、转换和优化前端资源。以下是它们的主要差异:
​
构建速度
Vite相比于Webpack在构建速度方面有优势。它采用了“按需编译”的方式,只编译修改过的文件,而其他未修改的文件则基本可以被复用,避免了不必要的重复构建过程,大大提升了开发体验和构建速度。
​
开发体验
Vite提供了快速的HMR(Hot Module Replacement)功能,可以使开发者在修改代码后,实时更新页面。相比之下,Webpack的HMR功能需要额外的配置和插件支持。
​
配置
Vite配置起来相对简单,不需要额外的配置文件,大多数配置可以通过Vite的内置配置完成,比如自定义别名、模块引入方式、热更新等。而Webpack则需要更复杂的配置文件。
​
生态支持
Webpack的生态非常丰富,有大量的插件和loader可供选择,可以满足各种需求。相比之下,Vite还比较年轻,虽然也有相应的插件可用,但是相对较少。
​
兼容性
Webpack支持更广泛的浏览器和Node.js版本,而Vite则只支持最新版本的Chrome和Node.js环境。
​
结论:Vite适用于开发体验优先、性能需求高的项目,包括中大型应用和复杂的组件库;而Webpack则适用于需要更多自定义配置、生态支持更全面的项目,适用于大型应用或定制化项目。

Ø 安装webpack打包工具到本机

Ø 熟知webpack的核心配置

Ø 配置好开发环境devServer

Ø 配置好相关的loader和plugin

一、webpack

官网:webpack

webpack | webpack中文文档 | webpack中文网

1.1、webpack是什么

webpack是一种前端资源构建工具,一个静态模块打包器.在webpack看来,前端的所有资源文件(js/json/css/image/less/sass...)都会作为模块处理。它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源。webpack可以解决当前web开发中所面临的困境,webpack提供了:

Ø 友好的模块化支持

Ø 代码压缩混淆

Ø 处理js/css兼容问题

Ø 性能优化(模块删减)-- tree-shaking(树摆)

注:webpack默认只能针对于js来进行打包处理

目前绝大多数企业中的前端项目,都是基于webpack进行打包构建的(vue/react)。

从 v4.0.0 开始之后,webpack默认可以不用进行任何的配置就可以进行打包工作,然而默认的打包方式不能够满足实际的生产需要,所以还需要进行对应的手动配置。
默认配置文件: webpack.config.js 或 webpackfile.js.

webpack4.0之后,在使用webpack时安装两个包 webpack webpack-cli

1.2 webpack五个核心配置

1.2.1 entry入口

字符串,数组,对象

本项目应该使用哪个模块,来作为构建其内部依赖图的开始(指定打包入口文件)

vue: src/main.js

react: src/index.js

1.2.2 output输出

对象

在哪里输出它所创建的 bundle,以及如何命名这些文件,默认值为 ./dist

vue: dist

react: build

1.2.3mode 模式

字符串

通过选择 development(开发) 或 production(生产) 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化

development: 代码不压缩

production: 代码压缩

1.2.4 loader 加载器(modules)

对象,里面写数组

loader让webpack能够去处理那些非js文件(webpack自身只理解js)

1.2.5 plugins 插件

数组

插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。

1.3 安装webpack

安装方式2种

Ø 全局安装

javascript 复制代码
cnpm i -g webpack webpack-cli

Ø 局部安装

webpack是运行在node环境中的,Node >= 8.10 和 npm >= 5.6

javascript 复制代码
$ cnpm init -y
​
$ cnpm i -D webpack webpack-cli
#打包使用的核心代码 webpack
​
#打包使用时的命令 webpack-cli

安装好后可以通过先前检查webpack的版本以确定是否安装成功:

webpack --version

在package.json文件中配置webpack运行脚本命令

javascript 复制代码
"scripts": {
  "build": "webpack"
 },
- webpack-course
	- config
		webpack.config.js
	- src
		main.js
	.gitignore
	package.json

1.4webpack基本使用

webpack默认情况下,会在./src目录下面去找index.js入口文件,默认是不需要任何的webpack配置。

默认入口 src/index.js

默认出口 dist/main.js

在项目根目录下面创建一个config/webpack.config.js文件,此文件是webpack的默认配置文件名称,后续就可以在此目录下面对webpack进行运行打包配置

修改package.json中的运行命令

javascript 复制代码
{
  "name": "webpack-course",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --config config/webpack.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.90.3",
    "webpack-cli": "^5.1.4"
  }
}

如果 配置文件在项目的根目录,则不需要 通过 --config 设置配置文件

假如设定 src/main.js作为项目的入口文件,则创建 webpack-course/src/main.js

javascript 复制代码
// config/webpack.config.js
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
module.exports = function () {
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      filename: 'static/js/[name].[contenthash:8].js' 
    }
  }
}

如果多次打包,发现 build 文件夹下出现更多打包的文件,并没有删除之前的,需要手动删除

复制代码
# 删除打包的build目录
bash 复制代码
$ cnpm i -D clean-webpack-plugin
javascript 复制代码
// config/webpack.config.js
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = function () {
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      filename: 'static/js/[name].[contenthash:8].js' 
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin() // 清除缓存文件
    ]
  }
}

1.5 配置访问入口模板文件

在项目根目录下面创建一个public目录,并在此目录中创建一个index.html文件,

html 复制代码
<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpack course</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

使用webpackhtml-webpack-plugin插件,可以将此文件用于项目web入口文件模块

复制代码
# 安装
javascript 复制代码
$ cnpm i -D html-webpack-plugin
javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = function () {
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      filename: 'static/js/[name].[contenthash:8].js' 
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HtmlWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin({ // 自动配置页面模板文件
        template: './public/index.html',
        // 默认引入js在head内,可以修改为body
        inject: 'body',
        // 压缩
        minify: {
          // 删除html模版中的注释语句
          removeComments: true,
          // 压缩HTML代码
          collapseWhitespace: true,
          // 删除属性的引号
          removeAttributeQuotes: true
          // https://www.npmjs.com/package/html-webpack-plugin
        }
      })
    ]
  }
}

1.6 devServer创建

我们已经可以使用打包工具去将写好的代码进行打包了,但是在操作的过程中大家可能会发现有一个比较麻烦的地方:修改一次代码就得重新打包一次,那么有没有在开发阶段,编写代码后自动进行编译看效果并且最好还能提供web服务的功能呢?答案是有的,它就是webpack-dev-server自动化打包工具。

javascript 复制代码
# 安装 webpack-dev-server
$ cnpm i -D webpack-dev-server

给 package.json 添加启动命令

javascript 复制代码
 "scripts": {
    "start": "webpack serve --config config/webpack.config.js",
    "dev": "npm run start",
    "build": "webpack --config config/webpack.config.js"
  }
bash 复制代码
$ cnpm run start

发现在启动项目的过程中,会提示给你 可以通过 http://localhost:8080 访问项目

那么 如果想要修改 端口号呢?如果想要和react一样自动打开默认浏览器呢?如果项目请求遇到了跨域问题呢?

javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = function () {
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      filename: 'static/js/[name].[contenthash:8].js' 
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HtmlWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin({ // 自动配置页面模板文件
        template: './public/index.html',
        // 默认引入js在head内,可以修改为body
        inject: 'body',
        // 压缩
        minify: {
          // 删除html模版中的注释语句
          removeComments: true,
          // 压缩HTML代码
          collapseWhitespace: true,
          // 删除属性的引号
          removeAttributeQuotes: true
          // https://www.npmjs.com/package/html-webpack-plugin
        }
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    }
  }
}
// src/main.js
console.log('webpack course')
console.log('webpack course')

fetch('/myapi/pro/list').then(res => res.json()).then(res => {
  console.log(res)
})

数据打印成功说明代理设置没有问题

1.7 加载器

1.7.1 加载器概述

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

loader加载器可以协助webpack打包处理特定的文件模块了,例如:

Ø sass-loader可以打包处理.scss相关的文件

Ø css-loader可以处理css样关的文件

Ø babel可以处理js兼容模块

Ø 配置图片处理 ...

1.7.2 打包处理css文件

正如前面所说,webpack默认不能打包css文件,如果在没有安装css加载器的时候打包,包含css文件的项目则会报错:

javascript 复制代码
/* src/style.css */
body {
  background-color: #f66;
}
import './style.css'
console.log(1)
console.log(2)
console.log(3)
​
fetch('/myapi/pro/list').then(res => res.json()).then(res => console.log(res.data))

我们需要安装一个CSS的加载器才能让webpack帮助我们打包css文件。

所以要想打包css文件,则需要安装css加载器,该加载器的安装命令为:

javascript 复制代码
$ cnpm i -D style-loader css-loader

安装好需要的加载器后需要对webpack进行配置,告诉webpack当遇到css后缀的文件应该交由哪个加载器去处理。在webpack打包命令对应的module的rules数组中添加css-loader规则:

javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = function () {
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      filename: 'static/js/[name].[contenthash:8].js' 
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HtmlWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin({ // 自动配置页面模板文件
        template: './public/index.html',
        // 默认引入js在head内,可以修改为body
        inject: 'body',
        // 压缩
        minify: {
          // 删除html模版中的注释语句
          removeComments: true,
          // 压缩HTML代码
          collapseWhitespace: true,
          // 删除属性的引号
          removeAttributeQuotes: true
          // https://www.npmjs.com/package/html-webpack-plugin
        }
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: ['style-loader', 'css-loader'] // 使用的加载器 - 解读顺序从后到前
        }
      ]
    }
  }
}

在写加载器use的时候,需要注意:

  • use数组中指定的加载器顺序是固定的

  • 多个加载器调用的顺序是:从右向左、从下往上调用(倒序执行)

在配置好对应的css加载器后,webpack才能打包对应的css文件

思考?如果做到css的自动兼容处理

使用postcss对样式兼容处理

javascript 复制代码
$ cnpm i -D postcss postcss-loader postcss-preset-env

在项目根目录下面创建两个文件 postcss.config.js.browserslistrc

javascript 复制代码
// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-preset-env')
  ]
}
// .browserslistrc
>0.01%
last 100 version
not dead
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = function () {
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      filename: 'static/js/[name].[contenthash:8].js' 
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HtmlWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin({ // 自动配置页面模板文件
        template: './public/index.html',
        // 默认引入js在head内,可以修改为body
        inject: 'body',
        // 压缩
        minify: {
          // 删除html模版中的注释语句
          removeComments: true,
          // 压缩HTML代码
          collapseWhitespace: true,
          // 删除属性的引号
          removeAttributeQuotes: true
          // https://www.npmjs.com/package/html-webpack-plugin
        }
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: ['style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        }
      ]
    }
  }
}
/* src/style.css */
body {
  display: flex;
  background-color: #f66;
}

1.7.3 打包处理scss\less\stylus文件

安装css预处理loader

javascript 复制代码
$ cnpm i -D sass sass-loader dart-sass 
$ cnpm i -D less less-loader 
$ cnpm i -D stylus stylus-loader
javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = function () {
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      filename: 'static/js/[name].[contenthash:8].js' 
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HtmlWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin({ // 自动配置页面模板文件
        template: './public/index.html',
        // 默认引入js在head内,可以修改为body
        inject: 'body',
        // 压缩
        minify: {
          // 删除html模版中的注释语句
          removeComments: true,
          // 压缩HTML代码
          collapseWhitespace: true,
          // 删除属性的引号
          removeAttributeQuotes: true
          // https://www.npmjs.com/package/html-webpack-plugin
        }
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: ['style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        }
      ]
    }
  }
}

1.7.4 抽取单个css文件

开发环境下 使用 style-loader 生产环境下抽离css文件

安装插件

javascript 复制代码
$ cnpm i -D mini-css-extract-plugin
javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // ++++++++
module.exports = function (webpackEnv) {  // ++++++++
  console.log('666', webpackEnv)
  const isDev = webpackEnv.WEBPACK_SERVE  // ++++++++
  const isProd = webpackEnv.WEBPACK_BUILD  // ++++++++
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      // filename: 'static/js/[name].[contenthash:8].js' 
      filename: isProd ? 'static/js/[name].[contenthash:8].js' : isDev && 'static/js/bundle.js'  // ++++++++
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HTMLWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin(  // ++++++++
        Object.assign({}, { // 合并对象
          template: './public/index.html',
          // 默认引入js在head内,可以修改为body
          inject: 'body',
        }, isProd ? {
          minify: {
            // 删除html模版中的注释语句
            removeComments: true,
            // 压缩HTML代码
            collapseWhitespace: true,
            // 删除属性的引号
            removeAttributeQuotes: true
            // https://www.npmjs.com/package/html-webpack-plugin
          }
        } : undefined)),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash:8].css'
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        }
      ]
    }
  }
}

1.8 图片处理

webpack5以前处理,webpack5也可用

javascript 复制代码
$ cnpm i -D file-loader url-loader
javascript 复制代码
// src/main.js
// import './style.css'
// import './style.less'
// import './style.scss'
// import './style.styl'

import logo from './logo.svg' // 3KB
import banner from './banner1.jpg' // 93KB
console.log(logo)
console.log(banner)
console.log(1)
console.log(2)
console.log(3)

fetch('/myapi/pro/list').then(res => res.json()).then(res => console.log(res.data))


// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = function (webpackEnv) {
  console.log('666', webpackEnv)
  const isDev = webpackEnv.WEBPACK_SERVE
  const isProd = webpackEnv.WEBPACK_BUILD
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      // filename: 'static/js/[name].[contenthash:8].js' 
      filename: isProd ? 'static/js/[name].[contenthash:8].js' : isDev && 'static/js/bundle.js'
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HTMLWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin(
        Object.assign({}, { // 合并对象
          template: './public/index.html',
          // 默认引入js在head内,可以修改为body
          inject: 'body',
        }, isProd ? {
          minify: {
            // 删除html模版中的注释语句
            removeComments: true,
            // 压缩HTML代码
            collapseWhitespace: true,
            // 删除属性的引号
            removeAttributeQuotes: true
            // https://www.npmjs.com/package/html-webpack-plugin
          }
        } : undefined)),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash:8].css'
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        },
        { // ++++++++++++++++
          test: /\.(gif|jpe?g|png|svg|webp)$/i,
          use: [
            {
              // file-loader 属于 url-loader的基础模块
              loader: 'url-loader',
              options: {
                // limit 属于允许用户使用的图片大小的限制
                // 如果用户使用图片目前大于10KB,就会在build文件夹下出现在media文件夹内
                // 如果使用图片小于10KB,图片以base64形式展示
                limit: 10 * 1024, // 10KB
                name: '[name].[hash:8].[ext]',
                outputPath: 'static/media'
              }
            }
          ]
        }
      ]
    }
  }
}

webpack5内置了资源模块

javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = function (webpackEnv) {
  console.log('666', webpackEnv)
  const isDev = webpackEnv.WEBPACK_SERVE
  const isProd = webpackEnv.WEBPACK_BUILD
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      // filename: 'static/js/[name].[contenthash:8].js' 
      filename: isProd ? 'static/js/[name].[contenthash:8].js' : isDev && 'static/js/bundle.js'
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HTMLWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin(
        Object.assign({}, { // 合并对象
          template: './public/index.html',
          // 默认引入js在head内,可以修改为body
          inject: 'body',
        }, isProd ? {
          minify: {
            // 删除html模版中的注释语句
            removeComments: true,
            // 压缩HTML代码
            collapseWhitespace: true,
            // 删除属性的引号
            removeAttributeQuotes: true
            // https://www.npmjs.com/package/html-webpack-plugin
          }
        } : undefined)),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash:8].css'
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        },
        // { // ++++++++++++++++
        //   test: /\.(gif|jpe?g|png|svg|webp)$/i,
        //   use: [
        //     {
        //       // file-loader 属于 url-loader的基础模块
        //       loader: 'url-loader',
        //       options: {
        //         // limit 属于允许用户使用的图片大小的限制
        //         // 如果用户使用图片目前大于10KB,就会在build文件夹下出现在media文件夹内
        //         // 如果使用图片小于10KB,图片以base64形式展示
        //         limit: 10 * 1024, // 10KB
        //         name: '[name].[hash:8].[ext]',
        //         outputPath: 'static/media'
        //       }
        //     }
        //   ]
        // }
        // webpack5新增的
        { // +++++ 
          test: /\.(gif|jpe?g|png|svg)$/i,
          type: 'asset',
          generator: {
            filename: 'static/media/[name].[hash:8].[ext]'
          },
          parser: {
            dataUrlCondition: {
              // 小于10KB base64 大于10KB 文件
              maxSize: 10 * 1024
            }
          }
        }
      ]
    }
  }
}

1.9 复制资源

像项目中字体资源是不需要进行打包处理的,可以直接的通过复制方式给打包到目标目录中

javascript 复制代码
$ cnpm i -D copy-webpack-plugin
javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = function (webpackEnv) {
  console.log('666', webpackEnv)
  const isDev = webpackEnv.WEBPACK_SERVE
  const isProd = webpackEnv.WEBPACK_BUILD
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      // filename: 'static/js/[name].[contenthash:8].js' 
      filename: isProd ? 'static/js/[name].[contenthash:8].js' : isDev && 'static/js/bundle.js'
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HTMLWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin(
        Object.assign({}, { // 合并对象
          template: './public/index.html',
          // 默认引入js在head内,可以修改为body
          inject: 'body',
        }, isProd ? {
          minify: {
            // 删除html模版中的注释语句
            removeComments: true,
            // 压缩HTML代码
            collapseWhitespace: true,
            // 删除属性的引号
            removeAttributeQuotes: true
            // https://www.npmjs.com/package/html-webpack-plugin
          }
        } : undefined)),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash:8].css'
      }),
      new CopyWebpackPlugin({ // ++++++
        patterns: [
          {
            from: path.resolve('./public/favicon.ico'),
            to: path.resolve('./build')
          },
          // 继续拷贝别的资源
          {
            from: path.resolve('./public/logo192.png'),
            to: path.resolve('./build')
          },
          {
            from: path.resolve('./public/logo512.png'),
            to: path.resolve('./build')
          }
          
        ]
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        },
        // { // ++++++++++++++++
        //   test: /\.(gif|jpe?g|png|svg|webp)$/i,
        //   use: [
        //     {
        //       // file-loader 属于 url-loader的基础模块
        //       loader: 'url-loader',
        //       options: {
        //         // limit 属于允许用户使用的图片大小的限制
        //         // 如果用户使用图片目前大于10KB,就会在build文件夹下出现在media文件夹内
        //         // 如果使用图片小于10KB,图片以base64形式展示
        //         limit: 10 * 1024, // 10KB
        //         name: '[name].[hash:8].[ext]',
        //         outputPath: 'static/media'
        //       }
        //     }
        //   ]
        // }
        // webpack5新增的
        { // +++++ 
          test: /\.(gif|jpe?g|png|svg)$/i,
          type: 'asset',
          generator: {
            filename: 'static/media/[name].[hash:8].[ext]'
          },
          parser: {
            dataUrlCondition: {
              // 小于10KB base64 大于10KB 文件
              maxSize: 10 * 1024
            }
          }
        }
      ]
    }
  }
}

1.10 js兼容处理

webpack在不需要引入任何loader可以对于js进行打包处理,但是它不会对于js兼容性进行任何的处理,而我们编写的项目是需要在不同的浏览器中运行的,此时就需要对于js的兼容性在打包过程中进行对应的处理。使用babel来完成对应的js兼容处理

bash 复制代码
cnpm i -D babel-loader @babel/core @babel/preset-env core-js
javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = function (webpackEnv) {
  console.log('666', webpackEnv)
  const isDev = webpackEnv.WEBPACK_SERVE
  const isProd = webpackEnv.WEBPACK_BUILD
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      // filename: 'static/js/[name].[contenthash:8].js' 
      filename: isProd ? 'static/js/[name].[contenthash:8].js' : isDev && 'static/js/bundle.js'
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HTMLWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin(
        Object.assign({}, { // 合并对象
          template: './public/index.html',
          // 默认引入js在head内,可以修改为body
          inject: 'body',
        }, isProd ? {
          minify: {
            // 删除html模版中的注释语句
            removeComments: true,
            // 压缩HTML代码
            collapseWhitespace: true,
            // 删除属性的引号
            removeAttributeQuotes: true
            // https://www.npmjs.com/package/html-webpack-plugin
          }
        } : undefined)),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash:8].css'
      }),
      new CopyWebpackPlugin({ // ++++++
        patterns: [
          {
            from: path.resolve('./public/favicon.ico'),
            to: path.resolve('./build')
          },
          // 继续拷贝别的资源
          {
            from: path.resolve('./public/logo192.png'),
            to: path.resolve('./build')
          },
          {
            from: path.resolve('./public/logo512.png'),
            to: path.resolve('./build')
          }
          
        ]
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.js$/,
          exclude: /node_modules/, // 不解析的文件
          use: [
            { // +++++++++++++++++++
              loader: 'babel-loader',
              // 也可以不写optins,项目跟目录下用 babel.config.js 代替
              options: {
                presets: [
                  [
                    '@babel/preset-env',
                    {
                      // 按需加载
                      useBuiltIns: 'usage',
                      // 指定core-js版本
                      corejs: 3,
                      // 兼容性做到哪个版本的浏览器
                      targets: {
                        chrome: '75'
                      }
                    }
                  ]
                ]
              }
            }
          ]
        },
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        },
        // { // ++++++++++++++++
        //   test: /\.(gif|jpe?g|png|svg|webp)$/i,
        //   use: [
        //     {
        //       // file-loader 属于 url-loader的基础模块
        //       loader: 'url-loader',
        //       options: {
        //         // limit 属于允许用户使用的图片大小的限制
        //         // 如果用户使用图片目前大于10KB,就会在build文件夹下出现在media文件夹内
        //         // 如果使用图片小于10KB,图片以base64形式展示
        //         limit: 10 * 1024, // 10KB
        //         name: '[name].[hash:8].[ext]',
        //         outputPath: 'static/media'
        //       }
        //     }
        //   ]
        // }
        // webpack5新增的
        { // +++++ 
          test: /\.(gif|jpe?g|png|svg)$/i,
          type: 'asset',
          generator: {
            filename: 'static/media/[name].[hash:8].[ext]'
          },
          parser: {
            dataUrlCondition: {
              // 小于10KB base64 大于10KB 文件
              maxSize: 10 * 1024
            }
          }
        }
      ]
    }
  }
}
// 如果不做 options的说明,需要在项目的根目录下设置 babel.config.js 或者 .babelrc

// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        // 按需加载
        useBuiltIns: 'usage',
        // 指定core-js版本
        corejs: 3,
        // 兼容性做到哪个版本的浏览器
        targets: {
          chrome: '75'
        }
      }
    ]
  ],
  // 加载UI库时用的居多
  plugins: []
}

1.11 路径别名与导入后缀省略

javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = function (webpackEnv) {
  console.log('666', webpackEnv)
  const isDev = webpackEnv.WEBPACK_SERVE
  const isProd = webpackEnv.WEBPACK_BUILD
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      // filename: 'static/js/[name].[contenthash:8].js' 
      filename: isProd ? 'static/js/[name].[contenthash:8].js' : isDev && 'static/js/bundle.js'
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HTMLWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin(
        Object.assign({}, { // 合并对象
          template: './public/index.html',
          // 默认引入js在head内,可以修改为body
          inject: 'body',
        }, isProd ? {
          minify: {
            // 删除html模版中的注释语句
            removeComments: true,
            // 压缩HTML代码
            collapseWhitespace: true,
            // 删除属性的引号
            removeAttributeQuotes: true
            // https://www.npmjs.com/package/html-webpack-plugin
          }
        } : undefined)),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash:8].css'
      }),
      new CopyWebpackPlugin({ // ++++++
        patterns: [
          {
            from: path.resolve('./public/favicon.ico'),
            to: path.resolve('./build')
          },
          // 继续拷贝别的资源
          {
            from: path.resolve('./public/logo192.png'),
            to: path.resolve('./build')
          },
          {
            from: path.resolve('./public/logo512.png'),
            to: path.resolve('./build')
          }
          
        ]
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.js$/,
          exclude: /node_modules/, // 不解析的文件
          use: [
            { // +++++++++++++++++++
              loader: 'babel-loader',
              // 也可以不写optins,项目跟目录下用 babel.config.js 代替
              options: {
                presets: [
                  [
                    '@babel/preset-env',
                    {
                      // 按需加载
                      useBuiltIns: 'usage',
                      // 指定core-js版本
                      corejs: 3,
                      // 兼容性做到哪个版本的浏览器
                      targets: {
                        chrome: '75'
                      }
                    }
                  ]
                ]
              }
            }
          ]
        },
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        },
        // { // ++++++++++++++++
        //   test: /\.(gif|jpe?g|png|svg|webp)$/i,
        //   use: [
        //     {
        //       // file-loader 属于 url-loader的基础模块
        //       loader: 'url-loader',
        //       options: {
        //         // limit 属于允许用户使用的图片大小的限制
        //         // 如果用户使用图片目前大于10KB,就会在build文件夹下出现在media文件夹内
        //         // 如果使用图片小于10KB,图片以base64形式展示
        //         limit: 10 * 1024, // 10KB
        //         name: '[name].[hash:8].[ext]',
        //         outputPath: 'static/media'
        //       }
        //     }
        //   ]
        // }
        // webpack5新增的
        { // +++++ 
          test: /\.(gif|jpe?g|png|svg)$/i,
          type: 'asset',
          generator: {
            filename: 'static/media/[name].[hash:8].[ext]'
          },
          parser: {
            dataUrlCondition: {
              // 小于10KB base64 大于10KB 文件
              maxSize: 10 * 1024
            }
          }
        }
      ]
    },
    // 路径别名与导入后缀省略
    resolve: {// ++++++++++++++++++++++++++
      // 配置别名
      alias: {
        '@': path.resolve('./src')
      },
      // 缺省的后缀名
      extensions: [
        '.js', '.json', '.jsx', '.ts', '.tsx', '.css', '.scss', '.less', '.vue', '.svg', '.png', '.jpg'
      ]
    }
  }
}
import "@/style"
import logo from '@/logo'
import banner1 from '@/banner1'
console.log('webpack course')
console.log('webpack course', logo)
console.log('webpack course', banner1)

fetch('/myapi/pro/list').then(res => res.json()).then(res => {
  console.log(res)
})

1.12 tree-shaking

tree-shaking是webpack中自带的功能,其作用是去除项目中无用代码(一般指的都是自己所写代码),减少代码体积(涉及到第三方类库,往往不一定有效。)

前提:

Ø 必须使用es6模块化

Ø 开启production环境

在package.json文件中添加了 "sideEffects": false 表示所有代码都没有副作用(所有代码都可以进行tree shaking)

复制代码
问题:可能会把 css的@babel/polyfill (副作用)文件删除掉
解决:package.json文件中添加"sideEffects":["*.css"]

不考虑使用 低版本浏览器,建议直接设置为false 即可

1.13 externals忽略不打入的包

例如项目中使用从 CDN 引入 jQuery,而不是把它打包进来使用

javascript 复制代码
 cnpm i jquery -S

src/main.js

javascript 复制代码
import $ from 'jquery'

不添加 externals 属性 -出现jquery 32次,添加了 出现6次 ,也可以查看打包的文件的大小

// 记得把mode的选项设置为 development

javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = function (webpackEnv) {
  console.log('666', webpackEnv)
  const isDev = webpackEnv.WEBPACK_SERVE
  const isProd = webpackEnv.WEBPACK_BUILD
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      // filename: 'static/js/[name].[contenthash:8].js' 
      filename: isProd ? 'static/js/[name].[contenthash:8].js' : isDev && 'static/js/bundle.js'
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HTMLWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin(
        Object.assign({}, { // 合并对象
          template: './public/index.html',
          // 默认引入js在head内,可以修改为body
          inject: 'body',
        }, isProd ? {
          minify: {
            // 删除html模版中的注释语句
            removeComments: true,
            // 压缩HTML代码
            collapseWhitespace: true,
            // 删除属性的引号
            removeAttributeQuotes: true
            // https://www.npmjs.com/package/html-webpack-plugin
          }
        } : undefined)),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash:8].css'
      }),
      new CopyWebpackPlugin({ // ++++++
        patterns: [
          {
            from: path.resolve('./public/favicon.ico'),
            to: path.resolve('./build')
          },
          // 继续拷贝别的资源
          {
            from: path.resolve('./public/logo192.png'),
            to: path.resolve('./build')
          },
          {
            from: path.resolve('./public/logo512.png'),
            to: path.resolve('./build')
          }
          
        ]
      })
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.js$/,
          exclude: /node_modules/, // 不解析的文件
          use: [
            { // +++++++++++++++++++
              loader: 'babel-loader',
              // 也可以不写optins,项目跟目录下用 babel.config.js 代替
              options: {
                presets: [
                  [
                    '@babel/preset-env',
                    {
                      // 按需加载
                      useBuiltIns: 'usage',
                      // 指定core-js版本
                      corejs: 3,
                      // 兼容性做到哪个版本的浏览器
                      targets: {
                        chrome: '75'
                      }
                    }
                  ]
                ]
              }
            }
          ]
        },
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        },
        // { // ++++++++++++++++
        //   test: /\.(gif|jpe?g|png|svg|webp)$/i,
        //   use: [
        //     {
        //       // file-loader 属于 url-loader的基础模块
        //       loader: 'url-loader',
        //       options: {
        //         // limit 属于允许用户使用的图片大小的限制
        //         // 如果用户使用图片目前大于10KB,就会在build文件夹下出现在media文件夹内
        //         // 如果使用图片小于10KB,图片以base64形式展示
        //         limit: 10 * 1024, // 10KB
        //         name: '[name].[hash:8].[ext]',
        //         outputPath: 'static/media'
        //       }
        //     }
        //   ]
        // }
        // webpack5新增的
        { // +++++ 
          test: /\.(gif|jpe?g|png|svg)$/i,
          type: 'asset',
          generator: {
            filename: 'static/media/[name].[hash:8].[ext]'
          },
          parser: {
            dataUrlCondition: {
              // 小于10KB base64 大于10KB 文件
              maxSize: 10 * 1024
            }
          }
        }
      ]
    },
    // 路径别名与导入后缀省略
    resolve: {// ++++++++++++++++++++++++++
      // 配置别名
      alias: {
        '@': path.resolve('./src')
      },
      // 缺省的后缀名
      extensions: [
        '.js', '.json', '.jsx', '.ts', '.tsx', '.css', '.scss', '.less', '.vue', '.svg', '.png', '.jpg'
      ]
    },
    externals: { // 忽略不打入的包 // +++++++++
      jquery: 'jQuery'
    }, 
  }
}

1.14 搭建React

拷贝相关文件至 webpack-react 文件夹

javascript 复制代码
$ cnpm i
$ cnpm i -D @babel/preset-react
$ cnpm i -S react react-dom
$ cnpm i antd -S
javascript 复制代码
{
  test: /\.(js|jsx)$/, // ++++++++
    exclude: /node_modules/, // 不解析的文件
      use: [
        {
          loader: 'babel-loader',
          // 也可以不写optins,项目跟目录下用babel.config.js 代替
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  // 按需加载
                  useBuiltIns: 'usage',
                  // 指定core-js版本
                  corejs: 3,
                  // 兼容性做到哪个版本的浏览器
                  targets: {
                    chrome: '75'
                  }
                }
              ],
              [ // ++++++++
                '@babel/preset-react'
              ]
            ]
          }
        }
      ]
},

在打包入口文件中引入React并进行单页面应用的渲染

src/main.js

javascript 复制代码
import React from 'react'
import ReactDOM from 'react-dom/client'
import { ConfigProvider } from 'antd';
import App from '@/App'
import zhCN from 'antd/locale/zh_CN';
const root = ReactDOM.createRoot(document.getElementById('root'))

root.render(
  <ConfigProvider locale={zhCN}>
    <App />
  </ConfigProvider>
)

src/App.jsx

javascript 复制代码
import React from 'react';
​
import { Button } from 'antd';
function App(props) {
  return (
    <div>
      App
      <Button type="primary">Primary Button</Button>
    </div>
  );
}
​
export default App;

1.15 搭建Vue2

拷贝相关文件至 webpack-vue2文件夹

安装解析vue的相关loader和插件

javascript 复制代码
$ cnpm i
$ cnpm i -D vue-loader@15 vue-template-compiler@2   // 切记一定要注意vue开发配置版本
$ cnpm i -S vue@2 element-ui

在webpack.config.js中配置

javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = function (webpackEnv) {
  console.log('666', webpackEnv)
  const isDev = webpackEnv.WEBPACK_SERVE
  const isProd = webpackEnv.WEBPACK_BUILD
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      // filename: 'static/js/[name].[contenthash:8].js' 
      filename: isProd ? 'static/js/[name].[contenthash:8].js' : isDev && 'static/js/bundle.js'
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HTMLWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin(
        Object.assign({}, { // 合并对象
          template: './public/index.html',
          // 默认引入js在head内,可以修改为body
          inject: 'body',
        }, isProd ? {
          minify: {
            // 删除html模版中的注释语句
            removeComments: true,
            // 压缩HTML代码
            collapseWhitespace: true,
            // 删除属性的引号
            removeAttributeQuotes: true
            // https://www.npmjs.com/package/html-webpack-plugin
          }
        } : undefined)),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash:8].css'
      }),
      new CopyWebpackPlugin({ // ++++++
        patterns: [
          {
            from: path.resolve('./public/favicon.ico'),
            to: path.resolve('./build')
          },
          // 继续拷贝别的资源
          {
            from: path.resolve('./public/logo192.png'),
            to: path.resolve('./build')
          },
          {
            from: path.resolve('./public/logo512.png'),
            to: path.resolve('./build')
          }
          
        ]
      }),
      new VueLoaderPlugin()
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.vue$/,
          use:['vue-loader']
        },
        {
          test: /\.js$/,
          exclude: /node_modules/, // 不解析的文件
          use: [
            { // +++++++++++++++++++
              loader: 'babel-loader',
              // 也可以不写optins,项目跟目录下用 babel.config.js 代替
              options: {
                presets: [
                  [
                    '@babel/preset-env',
                    {
                      // 按需加载
                      useBuiltIns: 'usage',
                      // 指定core-js版本
                      corejs: 3,
                      // 兼容性做到哪个版本的浏览器
                      targets: {
                        chrome: '75'
                      }
                    }
                  ]
                ]
              }
            }
          ]
        },
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        },
        // { // ++++++++++++++++
        //   test: /\.(gif|jpe?g|png|svg|webp)$/i,
        //   use: [
        //     {
        //       // file-loader 属于 url-loader的基础模块
        //       loader: 'url-loader',
        //       options: {
        //         // limit 属于允许用户使用的图片大小的限制
        //         // 如果用户使用图片目前大于10KB,就会在build文件夹下出现在media文件夹内
        //         // 如果使用图片小于10KB,图片以base64形式展示
        //         limit: 10 * 1024, // 10KB
        //         name: '[name].[hash:8].[ext]',
        //         outputPath: 'static/media'
        //       }
        //     }
        //   ]
        // }
        // webpack5新增的
        { // +++++ 
          test: /\.(gif|jpe?g|png|svg)$/i,
          type: 'asset',
          generator: {
            filename: 'static/media/[name].[hash:8].[ext]'
          },
          parser: {
            dataUrlCondition: {
              // 小于10KB base64 大于10KB 文件
              maxSize: 10 * 1024
            }
          }
        }
      ]
    },
    // 路径别名与导入后缀省略
    resolve: {// ++++++++++++++++++++++++++
      // 配置别名
      alias: {
        '@': path.resolve('./src')
      },
      // 缺省的后缀名
      extensions: [
        '.js', '.json', '.jsx', '.ts', '.tsx', '.css', '.scss', '.less', '.vue', '.svg', '.png', '.jpg'
      ]
    },
    externals: { // 忽略不打入的包 // +++++++++
      jquery: 'jQuery'
    }, 
  }
}

src/main.js

javascript 复制代码
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#root',
  render: h => h(App)
});

src/App.vue

javascript 复制代码
<template>
  <div>
    {{  count  }}
    <el-button type="success" @click="count++">加1</el-button>
  </div>
</template>
​
<script>
export default {
  data () {
    return {
      count: 10
    }
  }
}
</script>

1.16 搭建vue3

bash 复制代码
$ cnpm i vue -S
$ cnpm i vue-loader -D
$ cnpm i element-plus -S
javascript 复制代码
// webpack 基于nodejs的 
// 书写配置文件得遵循 commonjs 规范  
//  export default   ×
// module.exports   √
// 可以暴露对象 也可以暴露一个函数返回一个对象,为了配置方便,采用函数返回对象形式
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader') // 解析vue3的
module.exports = function (webpackEnv) {
  console.log('666', webpackEnv)
  const isDev = webpackEnv.WEBPACK_SERVE
  const isProd = webpackEnv.WEBPACK_BUILD
  return {
    // mode 环境,development 开发环境,production生产环境
    // development 打包的项目代码不会压缩
    // production 生产环境 打包的项目代码会压缩
    mode: 'development',
    // 入口说明, 可以理解为从 package.json 所以在的目录开始计算路径
    // entry: './src/main.js', // 字符串
    // entry: ['./src/main.js'], // 数组写法
    entry: { // 对象写法
      app: './src/main.js'
    },
    // 出口说明
    output: {
      // 输出的路径一定式绝对路径
      // __dirname E:\workspace\bk2310\code\webpack-course\config
      // 确定打包文件的路径为 build
      path: path.resolve(__dirname, '../build'),
      // 打包出来的文件在 build/static/js
      // name标识输出的文件名
      // contenthash: 8 生成8位随机数,也可以直接写为 hash:8
      // filename: 'static/js/[name].js' // 此处的那么 代表的 entry中的 对象的写法的那个key
      // filename: 'static/js/[name].[hash:8].js' // [hash:8] 8位随机数
      // filename: 'static/js/[name].[contenthash:8].js' 
      filename: isProd ? 'static/js/[name].[contenthash:8].js' : isDev && 'static/js/bundle.js'
    },
    // webpack的插件,书写形式为一个数组
    plugins: [
      new CleanWebpackPlugin(), // 清除缓存文件
      // new HTMLWebpackPlugin(), // 打包的文件夹内自动生成了一个 index.html 文件并且引入了打包文件
      new HTMLWebpackPlugin(
        Object.assign({}, { // 合并对象
          template: './public/index.html',
          // 默认引入js在head内,可以修改为body
          inject: 'body',
        }, isProd ? {
          minify: {
            // 删除html模版中的注释语句
            removeComments: true,
            // 压缩HTML代码
            collapseWhitespace: true,
            // 删除属性的引号
            removeAttributeQuotes: true
            // https://www.npmjs.com/package/html-webpack-plugin
          }
        } : undefined)),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash:8].css'
      }),
      new CopyWebpackPlugin({ // ++++++
        patterns: [
          {
            from: path.resolve('./public/favicon.ico'),
            to: path.resolve('./build')
          },
          // 继续拷贝别的资源
          {
            from: path.resolve('./public/logo192.png'),
            to: path.resolve('./build')
          },
          {
            from: path.resolve('./public/logo512.png'),
            to: path.resolve('./build')
          }
          
        ]
      }),
      new VueLoaderPlugin()
    ],
    // 开发服务器的配置 https://www.webpackjs.com/configuration/dev-server#root
    devServer: {
      // 开启开发服务器的端口号
      port: 'auto', // 也可以写固定值
      // 开发服务器准备就绪,自动打开默认浏览器运行
      // open: true,
      // history 路由模式刷新页面404页面处理
      historyApiFallback: true,
      // 资源压缩
      compress: true,
      // 如果遇到代理问题
      proxy: [ // 写为数组形式
        {
          context: ['/myapi'],
          target: 'http://121.89.205.189:3000/api',
          changeOrigin: true,
          pathRewrite: {
            '^/myapi': ''
          }
        },
      ]
    },
    // 解析器loader的配置
    module: {
      rules: [ // 各中加载器 - 处理非js模块 以及 js 的高级语法
        {
          test: /\.vue$/,
          use:['vue-loader']
        },
        {
          test: /\.js$/,
          exclude: /node_modules/, // 不解析的文件
          use: [
            { // +++++++++++++++++++
              loader: 'babel-loader',
              // 也可以不写optins,项目跟目录下用 babel.config.js 代替
              options: {
                presets: [
                  [
                    '@babel/preset-env',
                    {
                      // 按需加载
                      useBuiltIns: 'usage',
                      // 指定core-js版本
                      corejs: 3,
                      // 兼容性做到哪个版本的浏览器
                      targets: {
                        chrome: '75'
                      }
                    }
                  ]
                ]
              }
            }
          ]
        },
        {
          test: /\.css$/, // 正则, 以.css为结尾的文件
          // style-loader 将css代码放置 head 标签内部
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader'] // 使用的加载器 - 解读顺序从后到前
        },
        {
          test: /\.(sass|scss)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] 
        },
        {
          test: /\.less$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'less-loader'] 
        },
        {
          test: /\.(styl|stylus)$/, 
          use: [isProd ? MiniCssExtractPlugin.loader : isDev && 'style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] 
        },
        // { // ++++++++++++++++
        //   test: /\.(gif|jpe?g|png|svg|webp)$/i,
        //   use: [
        //     {
        //       // file-loader 属于 url-loader的基础模块
        //       loader: 'url-loader',
        //       options: {
        //         // limit 属于允许用户使用的图片大小的限制
        //         // 如果用户使用图片目前大于10KB,就会在build文件夹下出现在media文件夹内
        //         // 如果使用图片小于10KB,图片以base64形式展示
        //         limit: 10 * 1024, // 10KB
        //         name: '[name].[hash:8].[ext]',
        //         outputPath: 'static/media'
        //       }
        //     }
        //   ]
        // }
        // webpack5新增的
        { // +++++ 
          test: /\.(gif|jpe?g|png|svg)$/i,
          type: 'asset',
          generator: {
            filename: 'static/media/[name].[hash:8].[ext]'
          },
          parser: {
            dataUrlCondition: {
              // 小于10KB base64 大于10KB 文件
              maxSize: 10 * 1024
            }
          }
        }
      ]
    },
    // 路径别名与导入后缀省略
    resolve: {// ++++++++++++++++++++++++++
      // 配置别名
      alias: {
        '@': path.resolve('./src')
      },
      // 缺省的后缀名
      extensions: [
        '.js', '.json', '.jsx', '.ts', '.tsx', '.css', '.scss', '.less', '.vue', '.svg', '.png', '.jpg'
      ]
    },
    externals: { // 忽略不打入的包 // +++++++++
      jquery: 'jQuery'
    }, 
  }
}

src/main.js

javascript 复制代码
import { createApp } from 'vue'
import App from '@/App'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const root = createApp(App)
root.use(ElementPlus)
root.mount('#root')

src/App.vue

javascript 复制代码
<template>
  <div>
    {{  count }}
    <!-- <button @click="count+=10">加10</button> -->
    <el-button type="primary" @click="count+=10">加10</el-button>
  </div>
</template>
<script setup>
  import { ref } from 'vue'
  const count = ref(10)
</script>
复制代码
相关推荐
Algorithm15765 分钟前
云原生相关的 Go 语言工程师技术路线(含博客网址导航)
开发语言·云原生·golang
m0_748255266 分钟前
easyExcel导出大数据量EXCEL文件,前端实现进度条或者遮罩层
前端·excel
shinelord明15 分钟前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
Monly2121 分钟前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
boligongzhu22 分钟前
DALSA工业相机SDK二次开发(图像采集及保存)C#版
开发语言·c#·dalsa
Eric.Lee202122 分钟前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
7yewh25 分钟前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
长风清留扬27 分钟前
小程序毕业设计-音乐播放器+源码(可播放)下载即用
javascript·小程序·毕业设计·课程设计·毕设·音乐播放器
waicsdn_haha36 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
_WndProc38 分钟前
C++ 日志输出
开发语言·c++·算法