webpack5-开发环境

121 阅读7分钟

官方文档:webpack.docschina.org/

webpack是什么?

webpack是个静态资源打包工具

为什么使用webpack

开发时我们使用框架(react、vue)、es6模块化语法、less/sass等css预处理器等语法进行开发
这样的代码要向在浏览器运行,必须经过编译生成浏览器识别的js、css等语法,才能运行
所以我们需要打包工具帮我们完成这些事
除此之外,打包工具还能压缩代码、做兼容性处理、提升代码性能等

功能介绍

webpack本身功能是有限的
1.开发模式:仅能编译js中的 ES Module语法
2.生产模式:能编译js中的 ES Module语法,还能压缩代码

基本使用

他会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去
输出的文件就是编译好的文件,就可以在浏览器运行了
我们将webpack输出的文件叫做 bundle

初始化package.json文件(包描述文件)

npm init -y

下载webpack、webpack-cli

npm i webpack webpack-cli -D

npx会将node_modules/.bin目录临时添加为环境变量,这样就可以访问.bin下的应用程序

写一个count.js 导出一个减法函数,写一个sum.js导出一个加法函数 最后导入到main.js 执行以下命令打包:

告诉webpack入口文件是: ./src/main.js 模式是:development开发模式
npx webpack ./src/main.js --mode=development
npx webpack ./src/main.js --mode=production

如果不打包,浏览器是识别不了ES Module语法的,打包后就可以在浏览器中运行了,而且生产环境下压缩了代码。\

5大核心概念

1.entry(入口)
指示webpack从哪个文件开始打包
2.output(输出)
指示webpack打包完的文件输出到哪里去,如何命名等
3.loader(加载器)
webpack本身只能处理js、json等资源,其它资源需要借助loader,webpack才能解析
4.plugin(插件)
扩展webpack的功能
5.mode(模式)
主要有两种模式:
开发模式:development
生产模式:production

基础配置

webpack会识别根目录中的webpack.config.js文件,根据里面的配置打包资源
webpack.config.js的基础配置:

const path = require('path');
module.exports = {
  // 入口
  entry: './src/main.js', // 用相对路径
  // 出口
  output: {
    // 文件输出路径
    path: path.resolve(__dirname, 'dist'), // 要求用绝对路径
    // 文件名
    filename: 'main.js'
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
    ]
  },
  // 插件
  plugins: [
    // plugin的配置
  ],
  // 模式
  mode: 'development'
}

开发模式介绍

顾名思义,我们开发代码时使用的模式
开发模式下我们主要做两件事:
1.编译代码,使浏览器识别运行
  开发时我们有样式资源、字体图标、图片资源、html资源等,webpack默认都不能处理这些资源,
  所以我们要加载配置来编译这些资源。
2.代码质量检查,树立代码规范
  提前检查代码的一些隐患,让代码运行时能更加健壮
  提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观

处理样式资源

安装loader:
npm i style-loader css-loader -D // 处理css资源
npm i less-loader -D  // 处理less资源
npm i sass-loader -D // 处理s[ac]ss资源
npm i stylus-loader -D // 处理stylus资源
配置:
module: {
    rules: [
      // loader的配置
      // css-loader
      {
        test: /\.css$/i, // 检测.css结尾的文件
        use: [
          "style-loader", // 将js中css通过创建style标签添加到html文件生效
          "css-loader" // 将css文件编译成commonjs模块到js中
        ], // use执行顺序从右向左
      },
      {
        test: /\.less$/i,
        use: [
          // compiles Less to CSS
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          // 将 Sass 编译成 CSS
          'sass-loader',
        ],
      },
      {
        test: /\.styl$/i,
        use: [
          'style-loader',
          'css-loader',
          // 将 stylus 编译成 CSS
          'stylus-loader',
        ],
      },
    ]
  },

处理图片资源

webpack4 需要借助file-loader和url-loader处理图片资源
webpack5内置了此功能,只需要打开此功能就能处理图片资源
{
  // 只需要打开此配置就行,不需要下载额外loader
  // 如果不对图片做额外优化可以没有此配置
  test: /.(png|jpe?g|gif|webp|svg)$/, 
  type: "asset",
  parser: {
    dataUrlCondition: {
      // 小于10kb的图片会转base64
      // 有点:减少请求数量。缺点:小图的体积会变大一点点(大图的体积会变大很多)
      maxSize: 10 * 1024 // 10kb
    }
  }
}

修改打包输出资源路径

我们希望js输出到js目录,图片输出到images目录,其它资源去其它资源对应的目录去,这样看着不乱,方便管理

改变入口文件的输出文件名
output: {
  // 所有文件输出路径
  path: path.resolve(__dirname, 'dist'), // 要求用绝对路径
  // 入口文件打包输出的文件名
  filename: 'static/js/main.js'
},
改变图片资源的输出路径
{
  test: /.(png|jpe?g|gif|webp|svg)$/, 
  type: "asset",
  parser: {
    dataUrlCondition: {
      maxSize: 10 * 1024
    }
  },
  generator: {
    // 输出图片名称
    // 将图片输出在static/images文件下
    // filename: 'static/images/[hash][ext][query]'
    // [hash:10] 代表hash值只取前10位
    filename: 'static/images/[hash:10][ext][query]'
  }
}

打包前清空上次打包内容

output: {
  path: path.resolve(__dirname, 'dist'),
  filename: 'static/js/main.js',
  // 自动清除上次打包的内容
  // 原理:在打包前,将整个path目录清空,再进行打包
  clean: true
}

打包字体图标

{
    // 打包字体资源
    // 若不需要进行额外配置,不需要进行针对media做任何配置,webpack会原封不动的输出出去
    // 如果需要打包mp3、MP4、avi等音视频资源,webpack识别不了他们,只需要在后面加配置即可
    test: /.(ttf|woff2?|mp3|mp4|avi)$/, 
    type: "asset/resource",
    generator: {
      // 改变资源输出后的路径
      filename: 'static/media/[hash:10][ext][query]'
    }
}

Eslint

可组装的javascript和JSX检查工具
意思是他是迎来检测:js、jsx语法的工具,可以配置各项功能
我们使用eslint,关键是写eslint配置文件,里面写上各种rules规则,将来运行Eslint时就会就会以写的规则对代码进行检查

eslint配置文件的写法有以下几种:

.eslintrc.*:新建文件位于项目根目录
1、.eslintrc
2、.eslintrc.js
3、.eslintrc.json
区别在于配置格式不一样
package.json中eslintConfig:不需要创建文件,在原有文件基础上写
Eslint会查找或自动读取他们,所以以上配置文件只需要存在一个即可

我们以.eslintrc.js配置文件为例

module.exports = {
  // 解析选项
  parserOptions: {}
  // 具体检查规则
  rules: [],
  // 继承其它规则
  extends: [],
  // ...
  // 其它规则详见: http://eslint.bootcss.com/docs/user-guide/configuring
}

解析选项

parserOptions: {
  "ecmaVersion": 6, // ES版本
  "sourceType": "module", // ES模块化
  "ecmaFeatures": { // ES其它特性
      "jsx": true, // 如果是react项目,就需要开启jsx语法
  }
}

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/

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

1、eslint官方规则: eslint:recommended
2、vue cli官方的规则:plugin:vue/essential
3、react cli官方的规则: react-app
例如在react中可以这样写配置:
// 继承其它规则
extends: ["react-app"],
rules: {
  // 我们的规则会覆盖掉react-app的规则
  // 所以想要修改规则直接改就是了
  semi: "error",
}

webpack配置eslint

eslint 在webpack4是用的loader去处理,但是在webpack5用的plugin去处理
1、安装插件
npm install eslint-webpack-plugin --save-dev
2、如果未安装 eslint >= 7 ,你还需先通过 npm 安装:
npm install eslint --save-dev
3、插件都需要引入,所有插件都是构造函数,需要用new 调用
const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  plugins: [
    // plugin的配置
    // eslint配置
    new ESLintPlugin({
      // 检测的目录
      context: path.resolve(__dirname, 'src')
    })
  ],
};

webpack配置好eslint后,会去找eslint配置文件
安装vscode中的eslint插件,会在我们写代码的时候就检查格式,
.eslintignore文件是该插件的忽略文件

// 忽略dist目录
dist

babel

主要是将es6等高级语法糖转化为向后兼容的js语法,以便运行在当前和就版本的浏览器
babel配置文件:

1、babel.config.*   位于项目根目录
   babel.config.js
   babel.config.json
2、.babelrc.*       位于项目根目录
   .babelrc
   .babelrc.js
   .babelrc.json
3、package.json中,babel:  在原有文件基础上写

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

babel配置

以babel.config.js为例
module.exports = {
  // 预设
  presets: [
    '@babel/preset-env' // 智能预设,允许使用更高级的js语法
  ]
}
presets预设:  简单理解就是一组babel插件,拓展babel功能
下面是几个预设例子:
1.@babel/preset-env: 一个智能预设,允许使用javascript预设
2.@babel/preset-react: 一个用来编译react jsx语法的预设
3.@babel/preset-typescript: 一个用来便于TypeScript语法的预设

安装babel

npm install -D babel-loader @babel/core @babel/preset-env webpack

webpack配置
webpack配置babel使用loader配置的

module: {
  rules: [
    // 配置babel
    {
      test: /\.js$/,
      exclude: /node_modules/, // 排除node_modules文件
      use: {
        loader: 'babel-loader',
        // options: { // 这里配置也行
        //   presets: ['@babel/preset-env']
        // }
      }
    }
  ]
}

处理HTML资源

之前我们打包后需要手动引入打包后的资源,如果每次打包资源文件的hash值变化时,每次打包都需要手动修改引入路径,很麻烦。
处理html资源,用到一个插件:HtmlWebpackPlugin
安装

npm install --save-dev html-webpack-plugin

webpack配置

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
  plugins: [
      new HtmlWebpackPlugin({
          // 模板,以public/index.html为模板,创建新的html文件
          // 新html文件的特点:1、和原来结构一致,2、自动引入打包输出的资源
          template: path.resolve(__dirname, 'public/index.html')
      })
  ],
};

开发服务器&自动化

每次写完代码,我们都需要输入指令才能编译代码,太麻烦了,我们希望一切自动化。
webpack-dev-server可以在本地搭建一个服务器,监视src目录下的文件,一旦发生变化就会重新打包。
下载webpack-dev-server

npm install webpack-dev-server -D

webpack配置

// 开发服务器(开发服务器是不会输出资源的,它是在内存中编译打包的)
devServer: {
    host: 'localhost', // 启动服务器的域名
    port: 3000, // 启动服务器端口号
    open: false, // 是否自动打开浏览器
},

启动服务器:

npx webpack server

开发环境配置总结

编译代码,能让代码在浏览器运行,同时做些兼容性处理,做些代码检查以及自动化,让开发更方便