Skip to content

Latest commit

 

History

History
943 lines (627 loc) · 18.4 KB

File metadata and controls

943 lines (627 loc) · 18.4 KB

介绍

笔记对 webpack 的常用实现进行了整理,适合于了解 webpack,想要快速温习或进行一些常见功能拓展的情况。

相关笔记:

文档梳理

  • webpack 不同环境的配置分离

示例&配置详解

  • 用 webpack-chain 的方式配置

准备环境

准备初始文件环境

- webpack-demo
  + public
    - index.html
  + src
    - banner.js
    - index.js
    - tabs.js

public/index.html

<body>
  <div>轮播图</div>
  <div>tabs标签页</div>
</body>

<script src="../src/index.js"></script>

src/banner.js

console.log('实现轮播图的业务逻辑')

src/tabs.js

console.log('实现tabs标签页的逻辑')

src/index.js

import './banner.js'
import './tabs.js'

此时用 Live Server 启动 index.html 会报错,因为直接使用了 import;

使用 webpack 可以解决这个问题,它内置了对 CommonJS 模块化的处理。

webpack的使用

包的局部管理

需要项目下存在 package.json 文件,如果不存在,可以通过如下命令生成。

yarn init

yarn init -y

🐬 该命令会跳过文件的基本配置,生成默认文件。

包的局部安装

# 安装依赖包
yarn add webpack webpack-cli -D

打包项目

方法一

./node_modules/bin/webpack

方法二

npx webpack

👻 若是在项目下直接运行 webpack,其会使用全局安装的 webpack。

方法三

package.json

"script": {
  "build": "webpack"
}
yarn build

🐢 结果:生成默认dist目录和打包后默认main.js文件,默认会打包src下的index.js

webpack的配置

目录/webpack.config.js

入口和出口

告诉webpack从哪开始打包, 打包后的文件生成在哪个位置。

属性 默认值 版本
entry ./src/index.js webpack4
output.path ./dist/main.js webpack4

更改出入口

const path = require("path")

module.exports = {
  entry: "./src/main.js",
  output: { 
    path: path.join(__dirname, "dist"),
    filename: "bundle.js", 
    clean: true // 每次打包前,删除原打包内容 v5.20.0+
  }
}
说明
entry 需要打包的源文件
output.path 输出地址,需为绝对路径
filename 打包后的文件名
path.resolve() 拼接路径
__dirname 当前文件所在的绝对路径,注意是双下划线

修改文件名

- src
  - index.js ==> main.js

重新打包后的结果

- dist2
  + bundle.js

配置出口文件名

const path = require("path")

module.exports = {
  entry: "./src/main.js", // 入口
  output: { 
    path: path.join(__dirname, "dist"), // 出口路径
    filename: "js/[name].[hash:8].js",  // 出口文件名
    // filename: "js/[name].[hash:8].[ext]"
  }
}

🐙 这里测试,如果使用 [ext] ,将会被当做字符串视作为文件名的一部分,不太理解;

🐬 这里相当于在打包目录下创建一个 js 文件夹,用于存放打包后的文件。

配置 说明
[name] 原文件名字
[hash:8] 生成 8 位哈希值
[ext] 原文件拓展名
[] 代表变量

打包流程图

image-20230302220743798

mode模式

module.exports = {
  mode: 'production',  // // 设置 process.env.NODE_ENV 的值
}
模式值 翻译 说明
development 开发阶段 简易打包,打包速度快
production 发布阶段 打包精细,打包速度慢
none 不使用任何默认优化配置

production 会对源码做一些丑化和优化;

development 会把 webpack 的 devtool 设置为 evel。

追踪错误

webpack.config.js

module.exports = {
  mode: 'development', // 开发阶段
  devtool: 'inline-source-map' // 建立js映射文件,方便调试代码和错误
};

自动生成html-插件

  1. 下载插件

    yarn add html-webpack-plugin  -D
  2. webpack.config.js

    // 引入自动生成 html 的插件
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
        // ...省略其他代码
        plugins: [
            // ...其它插件,
            new HtmlWebpackPlugin()
        ]
    }

    👻 默认配置会根据默认的内置模板生成入口文件。

  3. 打包并观察

    - dist
      + index.html # 自动引入bundle.js
      + bundle.js
  4. 自定义打包的html模版,和输出文件名字

    plugins: [
      new HtmlWebpackPlugin({
        template: './public/index.html',
        filename: 'index.html'
      })
    ]

启动本地服务器

修改代码需要打包才能看到最新效果,但打包的过程很耗时;

可以开起一个开发服务器, 在电脑内存中打包, 缓存一些已经打包过的内容, 只重新打包修改的文件, 最终运行加载在内存中给浏览器使用;

启动本地服务, 可实时更新修改的代码, 打包变化代码到内存中, 然后直接提供端口和网页访问。

基本使用

  1. 下载包

    yarn add webpack-dev-server -D
  2. 配置自定义命令

    package.json

    scripts: {
    	// ...
    	"serve": "webpack serve"
    }
  3. 启动webpack开发服务器

    yarn serve

配置方式一

package.json

"scripts": {
  // ...
  "serve": "webpack serve --port 8083 --open"
},

配置方式二

webpack.config.js

module.exports = {
    // ...其他配置
    devServer: {
      port: 3000, // 本地服务器占用的端口号
      open: true  // 服务器启动完成自动打开到浏览器
    }
}

处理css文件-加载器

测试

src/style/index.css

.banner {
  width: 100px;
  height: 100px;
  background-color: hotpink;
}

main.js

// 添加
import './style/index.css'

🐙 webpack 默认只能处理js类型文件,所以此时直接运行项目会报错。

支持配置

  1. 安装依赖

    yarn add style-loader css-loader -D
  2. webpack.config.js

    module.exports = {
        // ...其他代码
        module: { 
            rules: [ // loader的规则
              {
                test: /\.css$/, // 匹配所有的css文件
                // use数组里从右向左运行
                // 先用 css-loader 让webpack能够识别 css 文件的内容并打包
                // 再用 style-loader 将样式, 把css插入到dom中
                use: [ "style-loader", "css-loader"]
              }
            ]
        }
    }

处理less文件-加载器

测试

src/style/index.less

body {
  .tabs {
    width: 400px;
    height: 40px;
    background-color: pink;
  }
}

main.js

// 添加
import './style/index.less'

🐙 webpack 默认只能处理js类型文件,所以此时直接运行项目会报错。

支持配置

  1. 安装依赖

    yarn add less less-loader -D
  2. webpack.config.js

    module.exports = {
        // ...其他代码
        module: { 
            rules: [
              {
                // 使用less-loader, 让webpack处理less文件
                // 并能够将less转译成css代码
                test: /\.less$/,
                use: ["style-loader", "css-loader", 'less-loader']
              }
            ]
        }
    }

处理图片-加载器

测试

  1. 定义盒子结构

    <div class="box"></div>
    <div class="box2"></div>
  2. 通过样式设置背景图

    .box {
      width: 100px;
      height: 100px;
      background-image: url(../assets/logo_small.png);
    }
    
    .box2 {
      width: 100px;
      height: 100px;
      background-image: url(../assets/1.gif);
    }
  3. 打包

    会在打包目录下生成对应的一样数量的图片,且页面正常展示

配置

webpack5

module.exports = {
    // ...其他代码
    module: { 
        rules: [
          {
            test: /\.(png|jpg|gif|jpeg)$/i,
            type: 'asset'
          }
        ]
    }
}

打包后发现图片被转化为了 base64 在js文件中出现,包总体积略增大;推测是体积小的图才转:question:

🐳 博客也有 webpack4 的配置。

处理策略

  • 以8kb进行区分,小于8kb图片转成 base64 字符串

    • 好处是可以减少浏览器的请求次数,直接从js中读取
    • 缺点是如果图片太大,再转base64就会让图片的体积增大 30% 左右

处理字体文件-加载器

测试

  1. 准备并引入字体文件

    main.js

    // 引入字体图标文件
    import '../assets/fonts/iconfont.css'
  2. 使用字体图标样式

    public/index.html

    <i class="iconfont icon-weixin"></i>

配置

webpack5

module.exports = {
    // ...其他代码
    module: { 
        rules: [
          {
            // webpack5默认内部不认识这些文件, 所以当做静态资源直接输出即可
            test: /\.(eot|svg|ttf|woff|woff2)$/,
            type: 'asset/resource',
            generator: {
              filename: 'font-[name].[hash:6][ext]'
            }
          }
        ]
    }
}

按照上面的测试,这里配置与否没有影响文件数量和包体积大小

据说可配置可不配置,有什么区别吗:question:

🐳 博客也有 webpack4 的配置。

处理ES6-加载器

测试

main.js

// 添加
class App {
  static a = 123
}
console.log(App.a)

🐳 不是所有的浏览器都支持ES6,使用 Chrome 测试支持很多新语法,但无法保证全部都支持。

说明

babel-loader 可以让 webpack 对高版本js语法做降级处理后打包。

依赖 说明
@babel/core babel的核心库,所有的核心Api都在这个库里,这些Api供babel-loader调用
@babel/preset-env 一个预设的插件集合,包含了一组相关的插件,Bable中是通过各种插件来指导如何进行代码转换。该插件包含所有es6转化为es5的翻译规则

配置

  1. 安装包

    yarn add -D babel-loader @babel/core @babel/preset-env
  2. 配置规则

    module: {
      rules: [
        {
            test: /\.js$/,
            exclude: /(node_modules)/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/preset-env'] 
                }
            }
        }
      ]
    }

配置拓展名

配置后,导入对应类型文件时,可以省略后缀。

module.exports = {
  // 其他配置
  resolve: {
    extensions: [".js", ".css", ".vue"],
  },
};

配置别名

配置写法一

const path = require("path");
const resolve = (dir) => path.resolve(__dirname, dir);

module.exports = {
  // 其它配置
  resolve: {
    alias: {
      "@": resolve("src"),
      style: resolve("src/style"),
    },
  },
};

🐙 注意不要在配置中使用多个 resolve 属性,会报一些找不到头绪的error。

配置写法二

const path = require("path");

module.exports = {
  // 其它配置
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
      style: "@/style",
    },
  },
};

使用示例

import "@/style/index";
import "style/index.less";

配置版权信息-插件

const webpack = require('webpack')

module.exports = {
    ...
    plugins: [
        new webpack.BannerPlugin('最终版权归大自然所有')
    ]
}

压缩代码-插件

npm install uglifyjs-webpack-plugin -S -D

webpack.config.js

const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')

plugins: [
    new UglifyjsWebpackPlugin()
]

🌟 将删除所有的注释,与【配置版权信息的插件】冲突。

❓ webpack5 以上内置,应该只能应用于 webpack4 以下的版本,否则存在依赖版本问题。

启动项目时的提示-插件

npm install friendly-errors-webpack-plugin -D -S
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');

module.exports = {
  ...
  plugins: [
    new FriendlyErrorsPlugin({
      // 成功提示
      compilationSuccessInfo: {
        messages: [
          `open here: http://localhost:8080`,
        ],
      },
      onErrors: undefined,
    }),
  ]
}

筛选日志输出-配置

module.exports = {
    // ...其他配置
    stats: 'errors-only' // 只在发生错误时输出到控制台
}

👻 在启动项目时可以过滤掉分析信息,开发出错时的信息也更简洁。

编译报错页面提醒-配置

module.exports = {
    // ...其他配置
    devServer: {
      port: 3000, // 本地服务器占用的端口号
      // 当出现编译错误或警告时,在浏览器中显示全屏覆盖
      client: {
        overlay: {
          errors: true,
          warnings: false, // 警告时不进行全屏覆盖
        },
      },
    }
}

打包前清空打包文件-插件

webpack5.20+

const path = require("path")

module.exports = {
  // ...
  output: { 
    clean: true
  }
}

webpack低版本

npm install clean-webpack-plugin -D
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  plugins: [
    new CleanWebpackPlugin()
  ]
}

配置模版变量-配置

yarn add html-webpack-plugin  -D

index.html

<link rel="icon" href="%= BASE_URL %>favicon.icon">
<title><%= htmlWebpackPlugin.options.title %></title>

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 使用示例,非必须
const { DefinePlugin } = require('webpack'); // 内置模板,无需安装

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      title: "网页标题",
      template: "./public/index.html"
    }),
    new DefinePlugin({
      BASE_URL: "'./'"  // 需要内置引号,否则会在该上下文找对应变量
    })
  ]
}

复制资源-插件

对于不存在依赖关系的图片等本地资源,可以将它们放在打包后的资源目录下。

npm install copy-webpack-plugin -D
const CopyWebackPlugin = require('copy-webpack-plugin');

plugins: [
  new CopyWebackPlugin({
    patterns: [
      {
        from: "public",             // 需要复制的源位置
        to: "./",                   // 复制到的位置
        globOptions: {
          ignore: {                 // 忽略,不进行复制的资源
            "**/index.html"
          }
        }
      }
    ]
  })
]

🐢 可以忽略 CopyWebackPlugin 中的 to 配置项,它会自动读取上下文中的 output.path,即打包的目录下。

额外拓展

全局/本地webpack的使用

  • 全局使用
    • 项目文件下直接执行 webpack 命令
  • 局部使用
    • 项目文件下执行配置在 package.json 中的脚本命令,如 npm run build
    • 项目文件下,执行 node_modules/.bin/webpack 或相关命令

👻 package.json 中的脚本在执行时,先寻找本地的 node_modules/.bin 路径中的命令,找不到就到全局环境(更上级?)找;

👻 项目一般在局部安装 webpack(-S -D),因为不同的项目依赖的版本不同。

附录

参考资料:

补充的话

仓库,还提供了许多前端常见需求及实现的归纳整理,欢迎客官看看~

如果这篇笔记能够帮助到你,请帮忙在 github 上点亮 star,感谢!