Webpack: Plugin 学习——功能Plugin :在 webpack 打包输出的js文件比较小,将js文件变成行内内联样式添加到文件中

InlineChunkWebpackPlugin:

        webpack 打包生成的 runtime 文件太小了,额外发送请求性能不好,所以需要将其内联到 js 中,从而减少请求数量)——提升速度 runtime保存依赖和hash

嵌入到html中需要使用html-webpack-plugin插件

  1. html-webpack-plugin 输出 index.html 前将内联 runtime 注入进去
  2.  删除多余的 runtime 文件

首先需要在配置文件中进行打包输出runtime文件

  optimization:{
    splitChunks:{//代码分割
      chunks:'all'
    },
    runtimeChunk:{
      name:entrypoint => `runtime~${entrypoint.name}.js`,
    }
  },

 GitHub - jantimon/html-webpack-plugin: Simplifies creation of HTML files to serve your webpack bundles

根据这个配置 

 

下载依赖

 npm i safe-require -D

实现效果 

const HtmlWebpackPlugin = require("safe-require")("html-webpack-plugin");

class InlineChunkWebpackPlugin {
  constructor(tests) {
    this.tests = tests;
  }

  apply(compiler) {
    compiler.hooks.compilation.tap("InlineChunkWebpackPlugin", (compilation) => {
      // 1. 获取html-webpack-plugin的hooks
      const hooks = HtmlWebpackPlugin.getHooks(compilation);
      // 2. 注册 html-webpack-plugin的hooks -> alterAssetTagGroups
      hooks.alterAssetTagGroups.tap("InlineChunkWebpackPlugin", (assets) => {
        //3. 从里面将script的runtime文件,变成inline script
        /*
        assets.headTags: [
            {
              tagName: 'script',
              voidTag: false,
              meta: { plugin: 'html-webpack-plugin' },
              attributes: { defer: true, type: undefined, src: 'js/runtime~main.js.js' }
            },
           
        */
       /*修改成为
        assets.headTags: [
            {
              tagName: 'script',
              closeTag: true,
              meta: { plugin: 'html-webpack-plugin' },
              innnerHTML:runtime的内容
            },
       */
      //对里面的内容处理使用使用公共方法为了复用
        assets.headTags = this.getInlineChunk(assets.headTags, compilation.assets);
        assets.bodyTags = this.getInlineChunk(assets.bodyTags, compilation.assets);

        // console.log('assets:',assets)
        // console.log('assets.headTags:',assets.headTags)
        // console.log('assets.bodyTags:',assets.bodyTags)
      });

      // 删除runtime文件
      hooks.afterEmit.tap("InlineChunkWebpackPlugin", () => {
        // 3. 从里面将script的runtime文件,变成inline script
        Object.keys(compilation.assets).forEach((filepath) => {
          if (/runtime(.*)\.js$/g.test(filepath)) {
            delete compilation.assets[filepath];
          }
        });
      });
    });
  }
//定义方法 为了复用
  getInlineChunk(tags, assets) {
    /*
      目前:[
        {
          tagName: 'script',
          voidTag: false,
          meta: { plugin: 'html-webpack-plugin' },
          attributes: { defer: true, type: undefined, src: 'js/runtime~main.js.js' }
        },
      ]

      修改为:
        [
          {
            tagName: 'script',
            innerHTML: runtime文件的内容
            closeTag: true 
          },
        ]
    */

    return tags.map((tag) => {
      if (tag.tagName !== "script") return tag;//退出 一定要是script标签
      // 获取文件资源路径
      const filepath = tag.attributes.src;
      if (!filepath) return tag;//一定要有文件路径
//assets文件资源
     if (!/runtime(.*)\.js$/g.test(filepath)) return tag//包含runtime吗
      return {
        tagName: "script",
        innerHTML: assets[filepath].source(),
        closeTag: true,
      };
    });
  }
}

module.exports = InlineChunkWebpackPlugin;

 


为了匹配度更高,将传递的规则放在配置文件中

    new InlineChunkWebpackPlugin([/runtime(.*)\.js$/g])
const path = require("path");
//处理html
const HtmlWebpackPlugin = require("html-webpack-plugin");
//插件需要先引入再使用
const TestPlugin = require("./plugins/test-plugin2");
const BannerWebpackPlugin = require("./plugins/banner-webpack-plugin");
const CleanWebpackPlugin = require("./plugins/clean-webpack-plugin");
const AnalyzeWebpackPlugin = require("./plugins/analyze-webpack-plugin");
const InlineChunkWebpackPlugin = require("./plugins/inline-chunk-webpack-plugin");
module.exports = {
  entry: "./src/main.js",//根据找到依赖
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "js/[name].js",// filename: 输出文件名
    //clean: true,
  },
  module: {//编译记载配置
    rules: [
      //   {
      //   test: /\.js$/,//处理js文件
      //   loader: "./loaders/test-loader.js",//将要处理文件作为参数传到test-loader.js
      // },
      {
        test: /\.js$/,//处理js文件
        // use: ["./loaders/demo/test1","./loaders/demo/test2"],
          // loader: "./loaders/demo/test3",
          // use: ["./loaders/demo/test4","./loaders/demo/test5","./loaders/demo/test6"],
           loader: "./loaders/clean-log-loader",
      },
      {
        test: /\.js$/,//处理js文件
           loader: "./loaders/banner-loader/index.js",
           options:{
              author:"老王",
              // age:"34"
           }
      },
      {
        test: /\.js$/,
        loader: "./loaders/babel-loader",
        options: {
          presets: ["@babel/preset-env"],//传入的预设选项@babel/preset-env
        },
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        loader: "./loaders/file-loader",
        type: "javascript/auto", // 阻止webpack默认处理图片资源,只使用file-loader处理
      },
      {
        test: /\.css$/,
        // use: ["style-loader", "css-loader"],
        use: ["./loaders/style-loader","css-loader"],
      },

    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "public/index.html"),
    }),
    //new TestPlugin(),
    new BannerWebpackPlugin({
      author: "老王",
    }),
    new CleanWebpackPlugin(),
    new AnalyzeWebpackPlugin(),
    new InlineChunkWebpackPlugin([/runtime(.*)\.js$/g])
  ],

  optimization:{
    splitChunks:{//代码分割
      chunks:'all'
    },
    runtimeChunk:{
      name:entrypoint => `runtime~${entrypoint.name}.js`,
    }
  },
  
  mode: "production",
};

plugin文件为 

const HtmlWebpackPlugin = require("safe-require")("html-webpack-plugin");

class InlineChunkWebpackPlugin {
  constructor(tests) {
    this.tests = tests;//接收传入的数组
  }

  apply(compiler) {
    compiler.hooks.compilation.tap("InlineChunkWebpackPlugin", (compilation) => {
      // 1. 获取html-webpack-plugin的hooks
      const hooks = HtmlWebpackPlugin.getHooks(compilation);
      // 2. 注册 html-webpack-plugin的hooks -> alterAssetTagGroups
      hooks.alterAssetTagGroups.tap("InlineChunkWebpackPlugin", (assets) => {
        // 3. 从里面将script的runtime文件,变成inline script
        assets.headTags = this.getInlineChunk(assets.headTags, compilation.assets);
        assets.bodyTags = this.getInlineChunk(assets.bodyTags, compilation.assets);
      });

      // 删除runtime文件
      hooks.afterEmit.tap("InlineChunkWebpackPlugin", () => {
        // 3. 从里面将script的runtime文件,变成inline script
        Object.keys(compilation.assets).forEach((filepath) => {
          if (this.tests.some((test) => test.test(filepath))) {
            delete compilation.assets[filepath];
          }
        });
      });
    });
  }

  getInlineChunk(tags, assets) {
    /*
      目前:[
        {
          tagName: 'script',
          voidTag: false,
          meta: { plugin: 'html-webpack-plugin' },
          attributes: { defer: true, type: undefined, src: 'js/runtime~main.js.js' }
        },
      ]

      修改为:
        [
          {
            tagName: 'script',
            innerHTML: runtime文件的内容
            closeTag: true 
          },
        ]
    */

    return tags.map((tag) => {
      if (tag.tagName !== "script") return tag;
      // 获取文件资源路径
      const filepath = tag.attributes.src;
      if (!filepath) return tag;

      if (!this.tests.some((test) => test.test(filepath))) return tag;

      return {
        tagName: "script",
        innerHTML: assets[filepath].source(),
        closeTag: true,
      };
    });
  }
}

module.exports = InlineChunkWebpackPlugin;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值