levi_webpack总结

webpack 基本配置(可展开 && 收缩)

const os = require('os')
const { resolve } = require('path')
const webpack = require('webpack')
const HappyPack = require('happypack')
const WebpackBar = require('webpackbar')
const CopyPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
const CircularDependencyPlugin = require('circular-dependency-plugin')

const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
const source = resolve(__dirname, '..', 'src')

module.exports = {
  context: source,
  entry: {
    app: './index.tsx',
  },
  watchOptions: {
    // 不监听的 node_modules 目录下的文件
    ignored: /node_modules/,
  },
  stats: {
    assets: true,
    builtAt: true,
    colors: true,
    chunks: false,
    children: false,
    env: true,
    entrypoints: false,
    errors: true,
    errorDetails: true,
    hash: true,
    modules: false,
    moduleTrace: true,
    performance: true,
    publicPath: true,
    timings: true,
    version: true,
    warnings: true,
  },
  resolve: {
    unsafeCache: true,
    mainFiles: ['index'],
    mainFields: ['main'],
    extensions: ['.ts', '.tsx', '.js'],
    modules: [source, 'node_modules'],
    alias: {
      '@': source,
      'react-dom': '@hot-loader/react-dom',
      moment: 'dayjs',
      '@components': resolve(__dirname, '../src/components'),
      '@ant-design/icons/lib/dist$': resolve(__dirname, '../src/assets/icons.ts'),
    },
  },
  module: {
    rules: [
      {
        test: /\.((ts|js)(x?))$/,
        exclude: /node_modules/,
        include: [source],
        use: 'happypack/loader?id=babel',
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              outputPath: 'images',
              name: '[path][name].[ext]',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new WebpackBar(),
    new CopyPlugin([
      {
        from: resolve(__dirname, '../static'),
        ignore: ['dll/*'],
        to: resolve(__dirname, '../dist'),
      },
    ]),
    new HtmlWebpackPlugin({
      title: '新际通管理平台',
      filename: 'index.html',
      template: resolve(__dirname, '../public/index.html'),
      hash: true,
      minify: {
        removeRedundantAttributes: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true,
        removeComments: true,
        collapseBooleanAttributes: true,
      },
      // favicon: resolve(__dirname, '../public/favicon.ico'),
    }),
    new HappyPack({
      id: 'babel',
      threadPool: happyThreadPool,
      loaders: [
        'cache-loader',
        {
          loader: 'babel-loader',
          query: {
            cacheDirectory: './node_modules/webpack_cache/',
          },
        },
        'eslint-loader',
      ],
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, /dayjs$/),
    new HardSourceWebpackPlugin(),
    new CircularDependencyPlugin({
      exclude: /node_modules/,
      include: /src/,
      failOnError: true,
      allowAsyncCycles: false,
      cwd: process.cwd(),
    }),
  ],
}
复制代码

webpack 模块打包原理

下面谈谈我的理解
javascript 万物皆对象,每个实例都有一个proto属性,指向了他构造函数的原型对象
每个构造函数都有一个 prototype 属性,指向了他的原型对象

实例对象创建之间判断指向关系有 proto 代表指向关系 指向了原型对象

function A() {} // A 构造函数
var a = new A(); // a 实例对象

A.prototype; // 原型对象
a.__proto__ === A.prototype;
复制代码

所有函数都是由 Function 创建

A.__proto__ === Function.prototype; // true

Function.__proto__ === Function.prototype; // true
复制代码

Object 刚讲的是顶级函数,所以也是函数:(所有的鱼都归猫管哈哈哈哈哈)

Object.__proto__ === Function.prototype;
复制代码

所有的对象都是由 Object 构造函数创建的, 所以对象proto指向了 Object 的构造函数:

A.prototype.__proto__ === Object.prototype;
复制代码

Object.prototype 也是对象,比较特殊,指向了 null

Object.prototype.__proto__ === null;
复制代码

webpack 热更新原理

webpack 如何自定义loader,实现思路如何

webpack 如何自定义plugin,实现思路是如何

如何题提升webpack构建速度

  • 使用高版本的webpack和nodejs

  • 启用多进程构建(happypack/thead-loader)

  • 压缩代码

  • 使用mini-css-extract-plugin 提取公共css

  • terser-webpack-plugin 开启js多进程压缩

  • 缩小打包作用域

  • exclude/include (确定 loader 规则范围)

  • resolve.modules 指定解析第三方包的目录位置 (减少不必要的查找)

  • resolve.extensions 尽可能减少后缀尝试的可能性

  • 合理使用alias,简化导入

  • 提取页面公共资源

  • 使用 SplitChunksPlugin 进行(公共脚本、基础包、页面公共文件)分离(Webpack4内置) ,替代了 CommonsChunkPlugin 插件

  • 提取公共js资源 => splitChunks

    module.exports = {
        optimization: {
            splitChunks: {
                cacheGroups: {
                    utils: {
                        chunks: 'initial',
                        minSize: 0,
                        minChunks: 2
                    }
                }
            }
        }
    };
    复制代码
  • 利用缓存提升二次加载速度

  • hard-source-webpack-plugin

常见的loader有哪些,使用过哪些loader

  • file-loader
  • css-loader
  • image-loader
  • less-loader
  • babel-loader
  • ts-loader
  • eslint-loader

有哪些常用插件, 使用过哪些

  • html-webpack-plugin 简化html创建
  • mini-css-extract-plugin 提取css文件
  • define-plugin 定义环境变量 (Webpack4 之后指定 mode 会自动配置)
  • hardsource-webpack-plugin 启用缓存
  • happypack 多进程构建
  • webpack-bundle-analyzer 可视化 Webpack 输出文件的体积 (业务组件、依赖第三方模块)

webpack中loader和plugin区别

Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作

Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果

Loader 在 module.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个 Object,内部包含了 test(类型文件)、loader、options (参数)等属性。

Plugin 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。

webpack构建流程简述下

  • 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数
  • 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译
  • 确定入口:根据配置中的 entry 找出所有的入口文件
  • 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
  • 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
  • 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
  • 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统

在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。

简单说

  • 初始化:启动构建,读取与合并配置参数,加载 Plugin,实例化 Compiler
  • 编译:从 Entry 出发,针对每个 Module 串行调用对应的 Loader 去翻译文件的内容,再找到该 Module 依赖的 Module,递归地进行编译处理
  • 输出:将编译后的 Module 组合成 Chunk,将 Chunk 转换成文件,输出到文件系统中

webpack如何文件监听

webpack 开启监听有2种方式

  • 启动命令行添加 –watch
  • webpack 配置文件中 添加 watch: true

babel编译原理

  • 解析:将代码转换成 AST
  • 转换:访问 AST 的节点进行变换操作生产新的 AST
  • 生成:以新的 AST 为基础生成代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享