aurora blog
  • JS

    • 基本汇总
    • Date时间
    • Array方法
    • String 方法
    • Object方法
    • RegExp正则
    • Es6 新特性等
    • Event-Loop
    • Http and Https
    • for in和for of区别
    • Web Worker
    • Promise && async
    • 堆内存 & 栈内存
    • JS设计模式探索
    • npm & yarn
    • Fetch和Axios的区别
    • 学习及面试问题整理
    • URL 输入到页面加载过程
    • 跨域&nginx本地项目代理
  • FE框架

    • react

      • 基本用法
      • react生命周期
      • hooks 16.8版本后
      • Route原理
      • Redux源码解析
      • React16 Fiber
      • React-VirtualDOM
      • React事件委托机制
      • React性能优化
      • 状态管理方案对比
      • React 18新特性
    • vue

      • vue 基本用法
      • vue 生命周期
      • VirtualDOM
      • vue 事件委托
      • vue 架构
      • vue 状态管理
      • 问题等
    • React-Native

      • React-Native 基本用法
    • 微前端

      • 遇到的问题
    • 鸿蒙 harmony

      • harmony 基础
  • 构建工具

    • webpack

      • Webpack配置详解
      • Webpack的使用
      • Babel-polyfill
      • webpack面试题
    • vite

      • vite配置详解
      • vite面试题
    • rollup

      • Rollup配置详解
      • rollup面试题
    • 构建工具对比
  • 性能优化

    • 性能优化策略
    • 缓存策略
    • 性能优化面试题
  • 浏览器

    • 浏览器渲染原理
    • 浏览器缓存机制
    • 浏览器面试题
  • 工程化

    • 代码规范
    • 工程化面试题
  • 前端安全

    • XSS 攻击与防护
    • CSRF 攻击与防护
    • 前端安全面试题
  • 移动端开发

    • 移动端适配
    • 移动端开发面试题
  • 前端监控

    • 错误监控
    • 性能监控
    • 前端监控面试题
  • Typescript

    • Typescript详解
  • Servers

    • Nodejs
    • Nginx
  • Git命令

    • git常用规范
  • 数据库

    • mongodb
    • mongodb
  • Other

    • Jenkins自动化部署

Webpack的使用

  • 优化
  • splitChunks拆包
  • 定义全局变量(DefinePlugin)
  • webpack代理
  • .babelrc
  • .env
  • 优化输出的文件
  • webpack用到的插件
    • 常用插件配置示例
  • require.context是什么
  • Tree Shaking
  • 代码懒加载

优化

1.异步加载模块
2.提取第三库
3.代码压缩
4.去除不必要的插件
5.图片base64
6.按需加载
7.开启Gzip压缩

splitChunks拆包

  • Webpack4之SplitChunksPlugin
  • Webpack3的CommonsChunkPlugin(已废弃)
optimization: {
  splitChunks: {
    chunks: 'all', // 'initial' | 'async' | 'all'
    minSize: 20000, // 生成 chunk 的最小体积
    maxSize: 0, // 拆分前最大体积
    minChunks: 1, // 被引用次数
    maxAsyncRequests: 30, // 按需加载时的最大并行请求数
    maxInitialRequests: 30, // 入口点的最大并行请求数
    cacheGroups: {
      // 第三方库单独打包
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        priority: 10,
        reuseExistingChunk: true,
      },
      // 公共代码
      common: {
        minChunks: 2,
        priority: 5,
        reuseExistingChunk: true,
      },
      // 样式文件单独打包
      styles: {
        test: /\.(css|less|scss)$/,
        name: 'styles',
        chunks: 'all',
        enforce: true,
      },
    },
  },
}

定义全局变量(DefinePlugin)

//eslint 设置通过
 "globals": {
     "ENV": true
 },
 new webpack.DefinePlugin({
     //必须 JSON.stringify(),然后在eslint里面,global()通过一下
    ENV: JSON.stringify(process.env.ENV), // 执行环境
}),

webpack代理

  • webpack-dev-server
//在配置文件webpackDevServer.config.js添加,
//新版本直接在package.json 里面添加,但是只能添加一个并且是字符串,也可在src下添加setupProxy.js

const proxy = require('http-proxy-middleware');

module.exports = function (app) {
    app.use(
        proxy("/pic", {
            "target": "http://120.79.229.197:9000",
            "changeOrigin": true,
            "secure": false,
            "pathRewrite": {"^/pic": ""}
        })
    );
    app.use(
        proxy("/self", {
            "target": "http://localhost:9999",
            "changeOrigin": true,
            "secure": false,
            "pathRewrite": {"^/self": ""}
        })
    );
};

.babelrc

//新的版本已经支持在package.json里面直接修改
{{
   "presets": [
     [
     "@babel/preset-env", {
       "targets": {
         "chrome": 58,
         "ie": 11
       }
     }
   ], "react-app"],
   "plugins": [
     ["import", {
         "libraryName": "antd",
         "libraryDirectory": "es",
         "style": "css"
       }
     ],
     ["@babel/plugin-proposal-decorators", { "legacy": true }],  //用于转换装饰器代码的插件。
     [
       "@babel/plugin-transform-runtime",
       {
         "absoluteRuntime": false,
         "corejs": 2,
         "helpers": true,
         "regenerator": true,
         "useESModules": false
       }
     ]
   ],
   "env": {
     "production": {
       "plugins":  ["transform-remove-console"]
     }
   }
 }

.env

定义一些环境变量,可以通过process.env.[name]拿取出来

GENERATE_SOURCEMAP=false  //禁止输出.map文件

优化输出的文件

/**
* hash:hash是跟整个项目的构建相关,只要项目里有文件更改,整个项目构建的hash值都会更改
* 采用hash计算的话,每一次构建后生成的哈希值都不一样,即使文件内容压根没有改变。这样子是没办法实现缓存效果,我们需要换另一种哈希值计算方式,即chunkhash。
*
* chunkhash:根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值。
* 我们在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用chunkhash的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响。
* 
* filename:决定了entry入口文件输出文件的名称。 (main.js)
* 
* chunkFilename:决定了非入口(non-entry) chunk 文件的名称,比如按需加载(异步)模块的时候 (组件打包的js)
*/
//js文件的输出
output: {
    filename: 'js/[name].[hash:8].js',
    chunkFilename: 'js/[name].[chunkhash:8].js'
},
//css文件的输出
miniCssExtractPluginOption: {
    filename: 'css/[name].[hash:8].css',
    chunkFilename: 'css/[name].[chunkhash:8].css'
},
//img文件的输出
imageUrlLoaderOption: {
    limit: 1024*50,
    name: 'static/images/[name].[hash:8].[ext]'
},

webpack用到的插件

常用插件配置示例

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const WebpackBundleAnalyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    // 清理输出目录
    new CleanWebpackPlugin(),
    
    // 生成 HTML 文件
    new HtmlWebpackPlugin({
      template: './public/index.html',
      filename: 'index.html',
      chunks: ['index', 'vendors'],
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
      },
    }),
    
    // 提取 CSS 到单独文件
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash:8].css',
      chunkFilename: 'css/[name].[contenthash:8].css',
    }),
    
    // 定义环境变量
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production'),
      'process.env.API_URL': JSON.stringify('https://api.example.com'),
    }),
    
    // 打包分析(可选)
    // new WebpackBundleAnalyzer(),
  ],
};

require.context是什么

require.context 是 webpack 提供的一个 API,用于创建上下文,实现批量导入模块。

// 语法:require.context(directory, useSubdirectories, regExp)
// directory: 要搜索的目录
// useSubdirectories: 是否搜索子目录
// regExp: 匹配文件的正则表达式

// 示例:批量导入组件
const requireComponent = require.context(
  './components', // 组件目录
  true, // 是否查找子目录
  /\.vue$/ // 匹配的文件类型
);

requireComponent.keys().forEach(fileName => {
  const componentConfig = requireComponent(fileName);
  const componentName = fileName
    .replace(/^\.\//, '')
    .replace(/\.\w+$/, '');
  
  // 全局注册组件
  Vue.component(componentName, componentConfig.default || componentConfig);
});

// 示例:批量导入路由
const requireRoute = require.context('./routes', false, /\.js$/);
const routes = requireRoute.keys().map(fileName => {
  const route = requireRoute(fileName);
  return route.default || route;
});

Tree Shaking

Tree Shaking 用于移除未使用的代码,减少打包体积。

// webpack.config.js
module.exports = {
  mode: 'production', // 生产环境自动启用
  optimization: {
    usedExports: true, // 标记未使用的导出
    sideEffects: false, // 告知 webpack 可以安全地删除未使用的导出
  },
};

// package.json
{
  "sideEffects": [
    "*.css",
    "*.scss",
    "./src/polyfill.js"
  ]
}

代码懒加载

使用动态 import 实现代码分割和懒加载。

// 路由懒加载
const Home = () => import('./views/Home.vue');
const About = () => import('./views/About.vue');

// 组件懒加载
const HeavyComponent = () => import('./components/HeavyComponent.vue');

// 条件懒加载
if (condition) {
  import('./moduleA').then(module => {
    // 使用 module
  });
}
最近更新:: 2025/11/20 14:50
Contributors: sountstars, liyulai
Prev
Webpack配置详解
Next
Babel-polyfill