Webpack 完整指南

​🌈个人主页:前端青山
🔥系列专栏:Webpack篇
🔖人终将被年少不可得之物困其一生

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

目录

介绍

一、webpack

1.1、webpack是什么

1.2 webpack五个核心配置

1.2.1 entry入口

1.2.2 output输出

1.2.3mode 模式

1.2.4 loader 加载器(modules)

1.2.5 plugins 插件

1.3 安装webpack

1.4webpack基本使用

1.5 配置访问入口模板文件

1.6 devServer创建

1.7 加载器

1.7.1 加载器概述

1.7.2 打包处理css文件

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

1.7.4 抽取单个css文件

1.8 图片处理

1.9 复制资源

1.10 js兼容处理

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

1.12 tree-shaking

1.13 externals忽略不打入的包

1.14 搭建React

1.15 搭建Vue2

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种

Ø 全局安装

cnpm i -g webpack webpack-cli

Ø 局部安装

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

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

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

webpack --version

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

"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中的运行命令

{
  "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

// 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目录
$ cnpm i -D clean-webpack-plugin
// 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文件,

<!-- 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入口文件模块

# 安装

$ cnpm i -D html-webpack-plugin
// 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自动化打包工具。

# 安装 webpack-dev-server
$ cnpm i -D webpack-dev-server

给 package.json 添加启动命令

 "scripts": {
    "start": "webpack serve --config config/webpack.config.js",
    "dev": "npm run start",
    "build": "webpack --config config/webpack.config.js"
  }
$ cnpm run start

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

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

// 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文件的项目则会报错:

/* 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加载器,该加载器的安装命令为:

$ cnpm i -D style-loader css-loader

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

// 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对样式兼容处理

$ cnpm i -D postcss postcss-loader postcss-preset-env

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

// 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

$ cnpm i -D sass sass-loader dart-sass 
$ cnpm i -D less less-loader 
$ cnpm i -D stylus stylus-loader
// 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文件

安装插件

$ cnpm i -D mini-css-extract-plugin
// 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也可用

$ cnpm i -D file-loader url-loader
// 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内置了资源模块

// 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 复制资源

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

$ cnpm i -D copy-webpack-plugin
// 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兼容处理

cnpm i -D babel-loader @babel/core @babel/preset-env core-js
// 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 路径别名与导入后缀省略

// 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,而不是把它打包进来使用

 cnpm i jquery -S

src/main.js

import $ from 'jquery'

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

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

// 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 文件夹

$ cnpm i
$ cnpm i -D @babel/preset-react
$ cnpm i -S react react-dom
$ cnpm i antd -S
{
  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

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

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和插件

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

在webpack.config.js中配置

// 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

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

<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

$ cnpm i vue -S
$ cnpm i vue-loader -D
$ cnpm i element-plus -S
// 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

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

<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>

                

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/891289.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浏览器服务端文件下载控制(安全阻止、文件浏览器打开还是下载行为控制)

文章目录 简介Chrome已阻止不安全内容下载PDF直接打开txt、xml、js文件被自动打开了而不是下载阿里OSS设置response header阿里OSS修改metadata 简介 随着浏览器的发展&#xff0c;有很多安全方面的限制&#xff0c;对我们的文件下载行为产生了很大的影响。 在JavaScript下载…

云手机:社交平台运营的热门工具

随着互联网的飞速发展&#xff0c;社交平台已经成为企业推广和营销的核心渠道。传统的运营方式已经无法满足高效运营的需求&#xff0c;而云手机作为新兴工具&#xff0c;逐渐成为社交平台运营的前沿趋势。本文将深入分析云手机如何优化社交平台的运营流程&#xff0c;助力企业…

手机中的ip地址是什么意思?可以改手机ip地址吗

‌IP地址&#xff0c;作为手机与网络通信的关键要素&#xff0c;不仅承担着网络通信的基础角色&#xff0c;还涉及网络安全、位置定位以及网络管理等多重功能。了解手机IP地址的含义及其修改方法&#xff0c;对于保护个人隐私、突破网络访问限制等方面具有重要意义。 一、手机I…

如何将mov格式的视频转换mp4?5种解决方法任你选!

MOV即QuickTime影片格式&#xff0c;它是Apple公司开发的一种音频、视频文件格式&#xff0c;用于存储常用数字媒体类型。然而&#xff0c;它的兼容性主要局限于苹果生态系统。有时&#xff0c;我们需要IOS和Mac设备的视频图片保存到安卓手机或Windows系统中&#xff0c;却发现…

国标GB28181软件LiteGBS国标GB28181公网平台分享链接面临不生效该如何解决?

在当今社会&#xff0c;随着科技的飞速发展&#xff0c;各种新兴技术正以前所未有的速度融入我们的日常生活&#xff0c;其中&#xff0c;LiteGBS作为一种基于国标GB28181协议的视频监控平台&#xff0c;正以其独特的功能和广泛的应用领域&#xff0c;深刻地影响着我们的生活方…

MySQL-约束Constraint详解

文章目录 约束简介非空约束检查约束唯一约束列级约束与表级约束给约束起名字 主键约束主键概念以及注意事项 外键约束外键概念以及注意事项外键使用场景约束的删除与添加级联相关操作级联删除(on delete cascade)级联更新(on update cascade)级联置空(on delete set null) 约束…

使用js和canvas实现简单的网页打砖块小游戏

玩法介绍 点击开始游戏后&#xff0c;使用键盘上的←→控制移动&#xff0c;小球会不停移动&#xff0c;板子触碰小球时会反弹&#xff0c;碰撞到砖块时会摧毁砖块&#xff0c;如果没有用板子接住小球就游戏失败 代码实现 代码比较简单&#xff0c;直接阅读注释即可&#x…

抖音小游戏画图位置移动

文章目录 画图移动图形位置 画图 const canvas tt.createCanvas(); const context canvas.getContext(2d);context.width 500; context.height 500;let isPressing false; // 是否按下 let startX 0; let startY 0;context.fillStyle "#f00"; context.fillR…

骨传导耳机哪个牌子的最好?全面测评分享5大热门骨传导耳机

在当今快节奏的生活中&#xff0c;人们越来越重视健康与休闲的平衡&#xff0c;而音乐则是连接这两者的重要桥梁。对于经常进行户外活动或锻炼的人来说&#xff0c;传统入耳式耳机可能存在安全隐患&#xff0c;这时&#xff0c;骨传导耳机便成为了理想的选择。骨传导技术通过振…

82.【C语言】数据结构之顺序表

在软件开发中,存储列表常用顺序表或链表 1.线性表 定义:n个具有相同特性的数据元素的有限序列(相当于一条直线)(用数组存储),要求数据依次存储 2.分类 1.静态顺序表&#xff1a;使用定长数组存储元素 代码示例(写入Seqlist.h中) typedef int SLDataType;//将int重定义为SL…

Java:玩家打怪小游戏

今天&#xff0c;我们尝试用Java来做一个“打怪小游戏”&#xff0c;听名字就知道&#xff0c;我们是应该创建几个成员和怪物&#xff0c;还有知道知道成员和怪物的血量&#xff0c;一次攻击的伤害等等。。当然我们的游戏攻击模式是“回合制”&#xff08;其实是别的方法&#…

云开发 | 微信小程序云开发无法获取数据库数据

1.我在我的云数据库中创建了一个数据表&#xff08;即collection数据集&#xff09;userList,并且存入了两条用户信息数据 2. 想要通过按钮触发事件拿取数据库中数据并且打印在控制台时&#xff0c;获取数据失败&#xff0c;控制台无输出 3. 初始化 | 在开始使用数据库 API 进…

androidStudio编译导致的同名.so文件冲突问题解决

files found with path lib/arm64-v8a/libserial_port.so from inputs: ...\build\intermediates\library_jni\debug\jni\arm64-v8a\libserial_port.so C:\Users\...\.gradle\caches\transforms-3\...\jni\arm64-v8a\XXX.so 解决方式如下&#xff1a; 1.将gradle缓存文件删…

Linux系统——lvm逻辑卷

Linux系统——lvm逻辑卷 一、lvm逻辑卷1、lvm操作流程2、操作指令 二、逻辑卷操作1、创建逻辑卷1.1 /dev/cloud/openstack 5G xfs /cloud/openstack1.2 /dev/cloud/docker 10G ext4 /cloud/docker 2、逻辑卷扩容2.1 扩容流程2.2 需求一&#xff1a;扩容ext4文件系统的逻辑卷2.3…

新手给视频加字幕的方法有哪些?4种加字幕方法推荐!

在视频制作中&#xff0c;字幕不仅是传递信息的重要手段&#xff0c;还能增强视频的观感和专业性。对于新手来说&#xff0c;如何给视频添加字幕可能是一个挑战。本文将介绍字幕的类型、推荐添加字幕的工具&#xff0c;以及详细添加字幕方法&#xff0c;帮助新手轻松掌握视频字…

宠物咖啡馆业务自动化:SpringBoot框架的实现方法

3系统分析 3.1可行性分析 通过对本基于Spring Boot的宠物咖啡馆平台的设计与实现实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本基于Spring Boot的宠物咖啡馆…

微前端 Spa qiankun

简介 首先什么是微前端&#xff1f; 他是一个软件架构模式。借鉴了后端的为服务架构思想&#xff0c;是将复杂单一的前端进行拆分成多个可以独立开发、部署、维护的小型应用。不同的应用关注不同的业务。最终将其集成到一个主框架里面。简单来说就是先分后合。 传统前端开发的…

【Unity - 屏幕截图】技术要点

在Unity中想要实现全屏截图或者截取某个对象区域的图片都是可以通过下面的函数进行截取 Texture2D/// <summary>/// <para>Reads the pixels from the current render target (the screen, or a RenderTexture), and writes them to the texture.</para>/…

【氮化镓】低温对p-GaN HEMT迁移率、阈值电压和亚阈值摆幅的影响

本期分享一篇低温对p-GaN HEMT 迁移率、阈值电压和亚阈值摆幅影响进行表征和建模的研究论文。文章作者Shivendra Kumar Singh、Thien Sao Ngo、Tian-Li Wu(通讯作者)和Yogesh Singh Chauhan,分别来资源中国台湾阳明交通大学国际半导体技术学院、印度理工学院坎普尔分校电气工…

(二)Python输入输出函数

一、输入函数 input函数&#xff1a;用户输入的数据&#xff0c;以字符串形式返回&#xff1b;若需数值类型&#xff0c;则进行类型转换。 xinput("请入你喜欢的蔬菜&#xff1a;") print(x) 二、输出函数 print函数 输出单一数值 x666 print(x) 输出混合类型…