Webpack5 基础篇(二)

九 . 处理其他资源

开发中可能还存在一些其他资源,如音视频

module: {

rules: [

// loader 的配置

{

test: /\.(ttf|woff2?|map3|map4|avi)$/,

type: 'asset/resource',

generator: {

// 输出名称

filename: 'static/media/[hash:10][ext][query]'

}

}

]

}

十. 处理js资源

为什么还要处理js ,不是已经处理过了吗?

原因是: Webpack对 jc 处理是有限的,只能编译js中ES模块化语法,不能编译其他语法,导致js不能再IE等浏览器运行,所以我们希望做一些兼容性处理

其次开发中,团队对代码格式是有严格要求的,我们不能由肉眼去检测代码格式,需要使用专业的工具来检测.

  • 针对js兼容性处理,我们使用Babel来完成
  • 针对代码格式,我们使用ESlint来完成
  • 我们先完成ESlint,检测代码格式无误后,在由Babel做代码兼容性处理

Eslint

可组装的 js和JSX检查工具

这计划意思就是: 它是用来检测js和jsx语法的工具,可以配置各项功能

我们使用Eslint,关键是写Eslint配置文件,里面写上各种rules规则,将来运行Eslint时就会以写的规则对代码检查

1.配置文件

配置文件由很多种写法 :

  • .eslintrc .* : 新建文件,位于项目根目录

    .eslinrc

    .eslintrc.js

    .eslintrc.json
    区别在于配置格式不一样

  • package.json种eslintConfig : 不需要创建文件,在原有文件基础上写ESlint会查找和自动读取它们,所以以上配置文件只需要存在一个即可

注意: 现在版本升级, eslint 9.xx 不认识eslintrc.js ,只认识eslint.config.js

2. 具体配置

我们以eslint.config.js配置文件为例:

module.exports = {

// 解析选项

parserOptions: {},

// 具体检查规则

rules: {},

// 继承其他规则

extends: [],

// ...

// 其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring

};

1. parserOptions 解析选项

parserOptions : {

ecmaVersion: 6, //ES语法版本

sourceType: "module", // ES模块化

ecmaFeatures: {

//ES其他特性

jsx: true // 如果是React项目,就需要开启jsx语法

}

}

2. rules 具体规则
  • "off" 或 0 - 关闭规则
  • "warn" 或 1 - 开启规则, 使用警告级别的错误 : warn (不会导致程序退出)
  • "error" 或 2 - 开启规则,使用错误级别的错误: error (当被触发的时候,程序会退出)

rules : {

semi : "error", //禁止使用分号

'array-callback-return' : 'warn', //强制数组方法的回调函数中有return语句,否则警告

'default-case' : [

'warn', // 要求switch 语句中有default 分支,否则警告

{commentPattern: '^no default$' } //允许在最后注释 no Default ,就不会有警告了

],

eqeqeq: [

'warn', //强制使用 === 和!== ,否则警告

'smart' // https://eslint.bootcss.com/docs/rules/eqeqeq#smart 除了少数情况下不会有警告

],

}

更多规则详见: eslint 文档

  1. extends 继承

开发中一点点写rules规则太费劲了,所以有更好的办法,继承现有的规则

现有以下较为有名的规则:

  • Eslint 官方的规则: eslint:recommended
  • Vue Cli 官方的规则: plugin:vue/essential
  • React Cli 官方的规则 : react-app

//例如在React项目中, 我们可以这样写配置

module.exports={

extends: ["react-app"],

rules:{

//我们的规则会覆盖掉react-app 的规则

// 所以想要修改规则直接改就是了

eqeqeq: [ "warn", "smart"],

}

}

3. 在Webpack 中使用
1. 下载

npm i eslint-webpack-plugin eslint -D

  1. 定义Eslint 配置文件
  • .eslintrc.js
  • //这种写法在eslint 9 .xx 不支持 eslint 8 支持

module.exports = {

// 继承 Eslint 规则

extends: ["eslint:recommended"],

env: {

node: true, // 启用node中全局变量

browser: true, // 启用浏览器中全局变量

},

parserOptions: {

ecmaVersion: 6,

sourceType: "module",

},

rules: {

"no-var": 2, // 不能使用 var 定义变量

},

};

4. 配置

const path = require("path");

//eslint插件

const ESLintWebpackPlugin = require("eslint-webpack-plugin");

module.exports = {

entry: "./src/main.js",

output: {

path: path.resolve(__dirname, "dist"),

filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中

clean: true, // 自动将上次打包目录资源清空

},

module: {

},

plugins: [

new ESLintWebpackPlugin({

// 指定检查文件的根目录

context: path.resolve(__dirname, "src"),

}),

],

mode: "development",

};

5. 运行webpack,会看到eslint 出现的报错

3. VsCode Eslint 插件

打开VsCode,下载Eslint 插件,即可不用编译就能看到错误,可以提前解决

但是此时就会对项目所有文件默认进行eslint检查了,我们dist目录下的打包后文件就会报错,但是我们只需要检查src下面的文件,不需要检查dist下面的文件

所以可以使用Eslint 忽略文件解决,在项目根目录新建下面文件:

  • .eslintignore

忽略dist目录下所有文件

dist

Babel

js 编译器

主要用于将 ES6 语法编写的代码转换为向后兼容的js语法,以便能够运行在当前和旧版本的浏览器活其他环境中

1.配置文件

配置文件由很多种写法:

  • babel.config.*:新建文件,位于项目根目录

    • babel.config.js

    • babel.config.json

  • .babelrc.*:新建文件,位于项目根目录

    • .babelrc

    • .babelrc.js

    • .babelrc.json

  • package.jsonbabel:不需要创建文件,在原有文件基础上写

Babel会查找和自动读取它们,所以以上配置文件只需要存在一个即可

2.具体配置

我们以babel.config.js 配置文件为例:

module.exports={

//预设

presets:[ ],

};

简单理解: 就是一组Babel插件,扩展Babel 功能

  • @babel/preset-env: 一个智能预设,允许您使用最新的 JavaScript。

  • @babel/preset-react:一个用来编译 React jsx 语法的预设

  • @babel/preset-typescript:一个用来编译 TypeScript 语法的预设

3. 在Webpack 中使用

  1. 下载包

npm i babel-loader @babel/core @babel/preset-env -D

  1. 定义Babel 配置文件
  • babel.config.js

module.exports = {

presets: ["@babel/preset-env"],

};

3. 修改js文件代码为箭头函数

4. 配置

  • webpack.config.js

module:{
rules:[

//babel

{

test: /\.js$/,

exclude: /node_modules/, // 排除node_modules代码不编译

loader: 'babel-loader'

}
]
}

5.运行

十一. 处理html资源

为什么还要处理html资源?

传统写法, 如果不处理html 我们需要手动引入打包好的文件,可能会有多个,无法自动注入打包资源

1.下载包

npm i html-webpack-plugin -D

2.配置

plugins:[

new HtmlWebpackPlugin({

// 以 public/index.html 为模板创建文件

// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源

template: path.resolve(__dirname, "public/index.html"),

}),

]

十二. 开发服务器&自动化

每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化

1.下载包

npm i webpack-dev-server -D

2. 配置

// 开发服务器

plugins:[

],

devServer: {

host: "localhost", // 启动服务器域名

port: "3000", // 启动服务器端口号

open: true, // 是否自动打开浏览器

},

3. 运行指令

npx webpack serve

注意运行指令发生了变化

并且当你使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到dist目录下,开发时我们只关心代码能运行,有效果即可,至于代码被编译成什么样子,我们并不需要知道

十三 . 生产模式准备工作

生产模式是开发完成代码后,我们需要得到代码将来部署上线

这个模式下我们主要对代码优化,让其运行性能更好

优化主要从两个角度出发

    1. 优化代码运行性能
    1. 优化代码打包速度

生产模式准备

我们分别准备了两个配置文件来放不同的配置

1.文件目录

webpack.dev.js 开发模式配置文件

webpack.prod.js 生产模式配置文件

2. 修改webpack.dev.js

dev开发环境没有输出, 不需要指定输出目录,

文件目录变了,所以所有绝对路径需要回退一层目录才能找到对应的文件

javascript 复制代码
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: undefined, // 开发模式没有输出,不需要指定输出目录
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    // clean: true, // 开发模式没有输出,不需要清空输出结果
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
      {
        test: /\.styl$/,
        use: ["style-loader", "css-loader", "stylus-loader"],
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
  ],
  // 其他省略
  devServer: {
    host: "localhost", // 启动服务器域名
    port: "3000", // 启动服务器端口号
    open: true, // 是否自动打开浏览器
  },
  mode: "development",
};

3. 指令

npx webpack serve --config ./config/webpack.dev.js

4. 修改webpack.prod.js

javascript 复制代码
const path = require('path') //nodejs 核心模块,专门用来处理路径问题

//引入eslint
const ESLintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  //入口
  entry: './src/main.js',
  //输出
  output: {
    //所有文件的输出路径
    //__dirname:node.js的变量 获取当前文件的绝对路径
    path: path.resolve(__dirname, 'dist'), //绝对路径
    //入口文件打包输出文件名
    filename: 'static/js/main.js',
    //自动清空上次打包内容
    //原理: 在打包前,将path整个目录内容清空,在进行打包
    clean: true
  },
  //加载器
  module: {
    rules: [
      //loader的配置
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        test: /\.s[ac]ss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      //预处理器,styl
      {
        test: /\.styl$/,
        use: ['style-loader', 'css-loader', 'stylus-loader']
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
          }
        },
        generator: {
          //输出图片名称 [hash:8]取图片hash的前八位 [ext]取文件原来扩展名 [query]取query参数
          filename: 'static/images/[hash:8][ext][query]'
        }
      },
      //字体图标
      {
        test: /\.(ttf|woff2?)$/,
        type: 'asset/resource',
        generator: {
          filename: 'static/media/[hash:8][ext][query]'
        }
      },
      //音视频
      {
        test: /\.(ttf|woff2?|mp3|mp4|avi)$/,
        type: 'asset/resource',
        generator: {
          // 输出名称
          filename: 'static/media/[hash:10][ext][query]'
        }
      },
      //babel
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: 'babel-loader'
      }
    ]
  },
  //插件
  plugins: [
    // new ESLintWebpackPlugin({
    //   // 指定检查文件的根目录 src
    //   context: path.resolve(__dirname, 'src')
    // })
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, 'public/index.html')
    })
  ],
  // 开发服务器
  devServer: {
    host: 'localhost', // 启动服务器域名
    port: '5500', // 启动服务器端口号
    open: true // 是否自动打开浏览器
  },
  //模式
  mode: 'development'
}

5. 指令

npx webpack --config ./config/webpack.prod.js

6. 配置运行指令

为了方便运行不同模式的指令,我们将指令定义在package.json中scripts里面

// package.json

{

// 其他省略

"scripts": {

"start": "npm run dev",

"dev": "npx webpack serve --config ./config/webpack.dev.js",

"build": "npx webpack --config ./config/webpack.prod.js"

}

}

以后启动指令:

  • 开发模式: npm start 或 npm run dev
  • 生产模式: npm run build

十四. Css处理

提取 Css 成单独文件

Css文件目前被打包到js文件中,当js文件加载时,会创建一个style标签来生成样式这样对于网站来说,会出现闪屏现象,用户体验不好

我们应该是单独的css文件,通过link标签加载性能才好

1.下载包

npm i mini-css-extract-plugin -D

2.配置

  • webpack.prod.js
javascript 复制代码
const path = require('path')
const ESLintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, '../dist'), // 生产模式需要输出
    filename: 'static/js/main.js', // 将 js 文件输出到 static/js 目录中
    clean: true
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
      },
      {
        test: /\.s[ac]ss$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
      },
      {
        test: /\.styl$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'stylus-loader']
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
          }
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: 'static/imgs/[hash:8][ext][query]'
        }
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: 'asset/resource',
        generator: {
          filename: 'static/media/[hash:8][ext][query]'
        }
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, '../src')
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, '../public/index.html')
    }),
    new MiniCssExtractPlugin({ filename: 'static/css/main.css' })
  ],
  mode: 'production'
}

3,打包后的示例

控制css兼容性

1.下载

npm i postcss-loader postcss postcss-preset-env -D

2.配置

javascript 复制代码
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  'postcss-preset-env' // 能解决大多数样式兼容性问题
                ]
              }
            }
          }
        ]
      },
    
......后面省略 都一样 注意顺序 要在'css-load后面'
    
    ]
  },

3. 控制兼容性

我们可以在package.json 文件中添加browserslist 来控制样式的兼容性做到什么程度

{

//其他省略

"browserslist": ["ie >= 8"]

}

要想知道更多的browserslist 配置,查看browserslist 文档

以上为了测试兼容性所以设置兼容浏览器ie8以上

实际开发中我们一般不考虑旧版本浏览器了,所以我们可以这样设置:

{

//其他省略

"browserslist" : [ "last 2 version", "> 1 %", "not dead"]

}

4.合并配置

webpack.prod.js

javascript 复制代码
// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
  return [
    MiniCssExtractPlugin.loader,
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    preProcessor,
  ].filter(Boolean);
};
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: getStyleLoaders(),
      },
      {
        test: /\.less$/,
        use: getStyleLoaders("less-loader"),
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders("sass-loader"),
      },
      {
        test: /\.styl$/,
        use: getStyleLoaders("stylus-loader"),
      },
    ],
  },

Css压缩

1. 下载

npm i css-minimizer-webpack-plugin -D

2. 配置

webpack.prod.js

javascript 复制代码
//引入压缩插件
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
    // css压缩
    new CssMinimizerPlugin(),
  ],

十五. html压缩

默认生产模式已经开启了: html压缩和js压缩,不需要额外进行配置

十六. Webpack基础总结

本章我们学会了Webpack基本使用,掌握了以下功能:

1. 两种开发模式

  • 开发模式: 代码能编译自动化运行
  • 生产模式: 代码编译优化输出

2. Webpack 基本功能

  • 开发模式: 可以编译Es Module 语法
  • 生产模式: 可以编译Es Module 语法, 压缩js代码

3. webpack 配置文件

  • 5个核心概念

    entry

    output

    loader

    plugins

    mode

  • devServer配置

4.Webpack 脚本指令用法

webpack 直接打包输出

webpack serve 启动开发服务器,内存编译打包没有输出

相关推荐
转转技术团队36 分钟前
HLS 流媒体技术:畅享高清视频,忘却 MP4 卡顿的烦恼!
前端
程序员的程40 分钟前
我做了一个前端股票行情 SDK:stock-sdk(浏览器和 Node 都能跑)
前端·npm·github
KlayPeter41 分钟前
前端数据存储全解析:localStorage、sessionStorage 与 Cookie
开发语言·前端·javascript·vue.js·缓存·前端框架
沉默-_-43 分钟前
从小程序前端到Spring后端:新手上路必须理清的核心概念图
java·前端·后端·spring·微信小程序
裴嘉靖1 小时前
前端获取二进制文件并预览的完整指南
前端·pdf
李剑一1 小时前
uni-app使用瓦片实现离线地图的两种方案
前端·trae
木易 士心1 小时前
深入剖析:按下 F5 后,浏览器前端究竟发生了什么?
前端
几何心凉1 小时前
离开舒适区之后:从三年前端到 CS 硕士——我在韩国亚大读研的得失
前端·人工智能·年度总结
小二·1 小时前
前端测试体系完全指南:从 Vitest 单元测试到 Cypress E2E(Vue 3 + TypeScript)
前端·typescript·单元测试
pas1361 小时前
18-mini-vue element
前端·vue.js·ubuntu