Webpack 快速食用指南(上篇)

目录

Webpack 是什么?

资源网站

转化/构建

打包/合并

构建+打包

Webpack 概述

Webpack 核心概念

Webpack 最快上手

Webpack 配置文件

# 常用配置(需熟记)

Webpack 基础

打包 css

打包 HTML

打包 JS

打包图片

打包字体

两个常用插件

资源模块 Asset Modules

开发服务器 Dev Server


​​​​​​​

Webpack 是什么?

Webpack 是一个打包器(Module bundler)。它的主要⽬标是将 JS ⽂件打包在⼀起,
打包后的⽂件⽤于在浏览器中使⽤。同时,它也能够转换 (transform)、打包 (bundle) 或包
裹 (package) 任何资源。

资源网站

官⽹:https://webpack.js.org/
中⽂官⽹:https://webpack.docschina.org/
Github:https://github.com/webpack/webpack

转化/构建

将源代码转换成⽣产代码的过程。即把不支持的代码转成支持的代码。

打包/合并

把多个文件合并成一个文件。

构建+打包

@打包工具,即为Webpack。 

 除了可以处理js,各类型也可以。

 综上,Webpack的功能是

  • 将多个⽂件合并(打包),减少 HTTP 请求次数,从⽽提⾼效率
  • 对代码进⾏编译,确保浏览器兼容性
  • 对代码进⾏压缩,减⼩⽂件体积,提⾼加载速度
  • 检测代码格式,确保代码质量
  • 提供热更新服务,提⾼开发效率

Webpack 概述

Webpack 核心概念

  • ⼊⼝(Entry) 第一个被访问的源码文件 默认src/index.js
  • 出⼝(Output)打包后的输出文件 默认dist/main.js
  • 加载器(Loader)专门用来处理一类(非js)的工具
  • 插件(Plugins)实现除 loader 之外的其他功能
  • 模式(Mode)区分环境
    • development(开发环境:⾃动优化打包速度,添加⼀些调试过程中的辅助)
    • production(⽣产环境:⾃动优化打包结果)
    • none(运⾏最原始的打包,不做任何额外处理)
  • 模块(Module)
  • 依赖图(Dependency Graph)

Webpack 最快上手

Webpack 配置文件

配置⽂件是⽤来简化命令⾏选项的
配置前:webpack ./src/index.js --output-path ./dist --mode=development
配置后:webpack

默认的配置⽂件名称是 webpack.config.js
使⽤ Webpack 的过程,⼤部分就是跟配置⽂件打交道的过程
配置详情: https://www.webpackjs.com/configuration/

# 常用配置(需熟记)

/**
 * Webpack 的配置文件
 */
const { resolve } = require('path')

module.exports = {
  // 打包模式
  mode: 'production',

  // 入口文件
  entry: './src/index.js',

  // 出口配置
  output: {
    // 输出目录(输出目录必须是绝对路径)
    path: resolve(__dirname, 'output'),
    // 输出文件名称
    filename: 'bundle.js'
  },

  // 模块配置
  module: {
    rules: [
      // 指定多个配置规则
    ]
  },

  // 开发服务器
  devServer: {

  },

  // 插件配置
  plugins: [

  ]
}

Webpack 基础

打包 css

Loader 使用方式:

  • 在入口文件中以模块方式 import 引入css
  • 然后在 webpack.config.js 中,在 module 处添加 .css 文件的配置规则(注意各个 loader 的使用顺序 由下往上,由右往左)
module: {
    // 配置⽂件类型规则,不同的规则使⽤不同的 loader 进⾏处理
    rules: [
      {
         // test 后跟随正则表达式,匹配⽂件类型
         test: /\.css$/,
         // use 表示使⽤什么 loader 来处理上述类型的⽂件
         use: [
             // 2. 将 JS 中的样式⽂件,嵌⼊到⻚⾯的 style 标签中
             'style-loader',
             // 1. css-loader 将样式⽂件转成 CommonJS 模块,加载到 JS 中
             'css-loader'
         ]
         }
     ]
 }

插件使用方式:

  • 需要在 webpack.config.js 最前面通过 require 引入,在 module 处配置规则
  • 并在 plugins 处进行插件配置,实例化。
const { resolve } = require('path')
// 将 css 打包成独立文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 格式校验
const StylelintPlugin = require('stylelint-webpack-plugin')
// 压缩 css
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
    ...,
    module: {
        rules: [
          {
            test: /\.css$/i,
            // use 中 loader 的加载顺序:先下后上
            use: [
              // 3. 将 JS 中的样式,挂载到 <style> 标签中
              // 'style-loader',

              // 3. 将 CSS 打包到独立的文件中
              MiniCssExtractPlugin.loader,

              // 2. css-loader 按照 CommonJS 规范,将样式文件,输出到 JS 中
              'css-loader',

              // 1. 通过 postcss-loader 给样式属性添加浏览器前缀
              'postcss-loader'
            ]
          },

          {
            test: /\.less$/i,
            // use 中 loader 的加载顺序:先下后上
            use: [
              // 4. 将 JS 中的样式,挂载到 <style> 标签中
              // 'style-loader',

              // 4. 将 CSS 打包到独立的文件中
              MiniCssExtractPlugin.loader,

              // 3. css-loader 按照 CommonJS 规范,将样式文件,输出到 JS 中
              'css-loader',

              // 2. 兼容性补全前缀
              'postcss-loader',

              // 1. 将 less 转成普通的 CSS
              'less-loader'
            ]
          },

            {
             test: ,
             use: ['','']
            } // 可以指定多个配置规则
        ]
    },

    // 插件配置
    plugins: [

        new MiniCssExtractPlugin({
          filename: 'css/[name].css'
        }),

        new StylelintPlugin({
          // 指定需要进行格式校验的文件
          files: ['src/css/*.{css,less,sass,scss}']
        }),

        // 压缩 CSS
        new OptimizeCssAssetsPlugin()
      ]
}

额外配置项:

1. 将 css 打包成独立文件的插件 MiniCssExtractPlugin ----》 图片路径变动问题

// 原写法
rules: [
    {
       test: /\.css$/i,
       use: [

           // 3. 将 CSS 打包到独立的文件中
           MiniCssExtractPlugin.loader,
       
       ]
    }
]

// 改成
rules: [
    {
       test: /\.css$/i,
       use: [

         {
            loader: MiniCssExtractPlugin.loader,
            options: {
                publicPath: '../' // 为背景图⽚指定路径
            }
         }

       ]
    }
]

2. 兼容 添加前缀 ----》 需要对 postCss 进行配置,⽤来设置 autoprefixer 的设置标准(即需要指定兼容哪些浏览器)

  • 添加 PostCSS 的配置 - 在项⽬根⽬录下添加 postcss.config.js
    module.exports = {
      'plugins': [
        require('autoprefixer')
      ]
    }
  •  在 package.json 中指定好兼容规则 https://www.npmjs.com/package/browserslist
    "browserslist": [
        "last 1 version",
        "> 1%"
    ]

3. 配置 StyleLint 的校验规则

在 package.json 中指定好规则,使⽤ stylelint-config-standard 规则来检测代码

"stylelint": {
    "extends": "stylelint-config-standard",
    // 除了使⽤ stylelint-config-standard,我们还可以在 rules 字段中⾃定义校验规则
    // 如果不需要⾃定义规则,可以忽略 rules
    "rules": {
      "number-leading-zero": "never"
   }
}

关于安装:

  • css-loader 负责遍历 CSS ⽂件,将 CSS 转化为 CommonJS(将 CSS 输出到打包后的JS ⽂件中)
  • style-loader 负责把包含 CSS 内容的 JS 代码,挂载到⻚⾯的 style 标签当中
npm i css-loader style-loader -D
  • 转换 Less
npm i less less-loader -D
  • 将 CSS 打包成独立文件:mini-css-extract-plugin 插件
npm install mini-css-extract-plugin -D
  • 添加前缀,解决兼容问题
    • postcss-loader
    • autoprefixer
npm install postcss-loader autoprefixer -D
  • 校验样式
    • stylelint 校验样式⽂件的命令 运行工具
    • stylelint-config-standard 校验样式⽂件的规则 推荐配置
    • stylelint-webpack-plugin 在 Webpack 中使⽤ stylelint 的插件
npm i stylelint stylelint-config-standard stylelint-webpack-plugin -D
  • 压缩 CSS  使用 optimize-css-assets-webpack-plugin 插件
npm install optimize-css-assets-webpack-plugin -D

打包 HTML

使用插件 html-webpack-plugin。

 跟上面的方法一样,在 webpack.config.js 中 require 这个插件,配置:

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

module.exports = {
    ...,
    plugins: [
        new HtmlWebpackPlugin() // 添加这⼀⾏
    ]
}

 可以在实例化的时候,进行 HTML 模板的设置。

plugins: [
    
    // Html 的配置
    new HtmlWebpackPlugin({
      // 指定打包后的文件名称
      filename: 'index.html',

      // 用来指定,生成 HTML 的模板
      template: './src/index.html',
      // 指定 HTML 中使用的变量
      title: "Webpack Demo"
    }),

    new HtmlWebpackPlugin({
      // 指定打包后的文件名称
      filename: 'about.html',
      // 用来指定,生成 HTML 的模板
      template: './src/index.html',
      // 指定 HTML 中使用的变量
      title: "关于我们",
      
      // 还可以在这里设置压缩
      minify: {
        collapseWhitespace: true,        // 折叠空⽩区域
        keepClosingSlash: true,
        removeComments: true,            // 移除注释
        removeRedundantAttributes: true, // 删除多余的属性
        removeScriptTypeAttributes: true,
        removeStyleLinkTypeAttributes: true,
        useShortDoctype: true
      }
    })

]

HTML 模板长这个样子

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>

  <h1>Hello Webpack</h1>
  <a href="index.html">首页</a>
  <a href="about.html">关于</a>
  
</body>
</html>

打包 JS

1. 为了保证 JS 在低版本浏览器的兼容性。

安装 babel-loader

  • @babel/core 包含 Babel 转换的核⼼ API 
  • @babel/preset-env 包含最新 JS 语法的转换规则 (只能转译基本语法)
  • babel-loader 是 Webpack 中,转换 JS 的加载器
npm install babel-loader @babel/core @babel/preset-env -D

// 按需转译 JS 新语法
npm i core-js -D

配置 webpack.config.js

module: {
  rules: [
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              [
                '@babel/preset-env', 
                { 
                  // 按需加载
                  useBuiltIns: 'usage',
                  // core-js 的版本
                  corejs: 3,
                  // targets: "defaults" 
                  // 指定兼容浏览器的版本
                  targets: {
                    chrome: '58',
                    ie: '9',
                    firefox: '60',
                    safari: '10',
                    edge: '17'
                  }
                }
              ]
            ]
          }
        }
      }
]}

2. 格式校验 eslint-webpack-plugin

npm i eslint eslint-config-airbnb-base eslint-webpack-plugin eslint-plugin-import -D

实例化 webpack.config.js

const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
    // ...
    plugins: [
        // new ESLintPlugin(options)

        new ESLintPlugin({
        // 自动解决常规的代码格式报错
        fix: true
        })

    ],
    // ...
};

指定 ESLint 配置 package.json

"eslintConfig": {
    "extends": "airbnb-base"
}

在js文件中,若要对某行不检查,采用如下注释。那么它的下一行就会跳过。

// eslint-disable-next-line

const showMsg = () => {
  // eslint-disable-next-line
  alert('Hello');
};

打包图片

  • file-loader 将用到的图片直接复制到 dist 目录下,过滤掉不⽤的图⽚
  • url-loader 将小于指定大小的图片,转成 base64,超过指定大小的图片依然使用 file-loader 进行复制
npm install file-loader url-loader -D

入口文件 index.js 

// 以模块的方式引入图片
import boy from './image/xph.gif';
import homeIcon from './image/icon/home-blue.png';


const img = new Image();
img.src = boy;
document.body.append(img);

实例化 webpack.config.js

const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
    // ...
    module: {
    rules: [
        {
            test: /\.(png|gif|jpe?g)$/i,
                 use: {
                 loader: "url-loader",
                 options: {
                 // 指定图片大小,小于该数值的图片,会被转成 base64
                 limit: 8 * 1024, // 8 kb
                 // [name] 是图片原来的名称
                 // [ext] 是图片原来的后缀名
                 name: "image/[name].[ext]",
            // url-loader 默认采用 ES Modules 规范进行解析,但是 html-loader 引入图片使用的是 CommonJS 规范
            // 解决:关闭 url-loader 默认的 ES Modules 规范,强制 url-loader 使用 CommonJS 规范进行打包
            //     esModule: false
               }
             }

            // 使用资源模块
            type: 'asset',
            parser: {
              dataUrlCondition: {
                maxSize: 8 * 1024
              }
            },
            generator: {
              filename: "image/[name][ext]"
            }
          }

          // {
          //   test: /\.(htm|html)$/i,
          //   use: {
          //     loader: 'html-loader',
          //     options: {
          //       // Webpack 4 中只需要在 url-loader 配置 esModule: false
          //       // Webpack 5 需要 html-loader 中,也配置 esModule: false
          //       esModule: false
          //     }
          //   }
          // }
           
};

能不能处理 HTML 中的 img 图片?

html-loader (将html导出为字符串,从而能被url-loader处理)适合处理没有使用ejs模板的html,这样就不会与 HtmlWebpackPlugin 冲突(不然它们会对同一份html起冲突,<img src="">与ejs语法)。

  • 所以,只需将 index.html 改为 index.ejs,然后把 plugins 中的模板名称对应替换。
  • 同时,<img src="<%= require('./image/icon/ok-black.png') %>" >
<!-- 旧写法 -->
<img src="./images/xph.gif" alt="">

<!-- 新写法 -->
<img src="<%= require('./images/xph.gif') %>" alt="">

这样,这份模板既可以被 HtmlWebpackPlugin 解析成功,又可以进行 url-loader 的处理,将图片替换成base64字符串。

打包字体

下载字体文件到fonts文件夹中。然后在css文件里添加该字体样式,再去html里引用该class。

配置 loader

{
test: /\.(eot|svg|ttf|woff|woff2)$/i,
   use: {
          loader: 'file-loader',
          options: {
              name: 'fonts/[name].[ext]'
        }
   }
}

两个常用插件

不需要处理的其他⽂件,可以直接复制到输出⽬录

每次打包之前,先删除输出⽬录中的历史⽂件(保证输出⽬录中的打包⽂件是最新的)

 实例化 webpack.config.js

const CopyWebpackPlugin = require('copy-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
    // ...
    plugins: [

      // 直接将 src 下,不需要特殊处理的文件,直接复制到输出目录中
      new CopyWebpackPlugin({
          patterns: [
              {
                from: "src/public",
                to: "public"
              }
          ]
      }),

    // 打包之前,先删除历史文件
    new CleanWebpackPlugin(),

    ],
    // ...
};

资源模块 Asset Modules

Webpack 5 提供了⼀个新的特性 - 资源模块。

通过资源模块也可以加载图⽚或字体,⽽⽆需配置额外的 loader。

 怎么用?

module.exports = {

 module: {
    rules: [     
      // 处理图片
      {
        test: /\.(png|gif|jpe?g)$/i,
        // use: {
        //   loader: "url-loader",
        //   options: {
        //     // 指定图片大小,小于该数值的图片,会被转成 base64
        //     limit: 8 * 1024, // 8 kb
        //     // [name] 是图片原来的名称
        //     // [ext] 是图片原来的后缀名
        //     name: "image/[name].[ext]",
        //   }
        // }

        // 使用资源模块
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024
          }
        },
        generator: {
          filename: "image/[name][ext]"
        }
      },



      // 匹配字体文件
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/i,
        // use: {
        //   loader: 'file-loader',
        //   options: {
        //     name: 'fonts/[name].[ext]'
        //   }
        // }

        // 使用资源模块处理字体文件
        // asset 可以在 asset/resource 和 asset/inline 之间进行选择
        // 如果文件小于 8kb,则使用 asset/inline 类型
        // 如果文件大于 8kb,则使用 asset/resource 类型
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024
          }
        },
        generator: {
          filename: "fonts/[name][ext]"
        }
      }
]}}

开发服务器 Dev Server

# 安装
npm i webpack-dev-server -g


# 运行

# webpack 4
webpack-dev-server ...

# webpack 5
webpack server ...

Webpack Dev Server 将打包内容放到内存中(而非磁盘),内存的读写性能远⼤于磁盘,因此
Webpack Dev Server 的热更新效率⼤于 browser-sync。(也因此不会生成 output 文件)
 

配置 webpack.config.js

  // 开发服务器
  devServer: {
    // 指定加载内容的路径
    contentBase: resolve(__dirname, 'output'),

    // 启用 gzip 压缩
    compress: true,

    // 端口号
    port: 9200,

    // ⾃动打开浏览器
    open: true,

    // 启动自动更新(禁用 hot)
    liveReload: true,

    // 配置代理:解决接口跨域问题
    proxy: {
      // http://localhost:9200/api
      '/api': {
         // http://localhost:9200/api/users => https://api.github.com/api/users
         target: 'https://api.github.com',
         // http://localhost:9200/api/users => https://api.github.com/users
         pathRewrite: {
           '^/api': ""
         },
         // 不能使用 localhost:9200 作为 github 的主机名
         changeOrigin: true
      }
    }
  },

  // 配置目标  写在外面,热更新的target
  target: "web",
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值