在上一篇文章中,利用不同位置的publicPath,对html中的cdn地址,进行了处理。但是,遗留了一个小问题,就是cssjscdn地址,并没有分开。

苏南大叔:webpack4系列教程,如何编写plugin处理html代码逻辑? - webpack-plugin-demo
webpack4系列教程,如何编写plugin处理html代码逻辑?(图4-1)

本文测试环境:win10node@14.2.0npm@6.14.4webpack@4.43.0

不大不小的误会

为了区分cssjspublicPath,苏南大叔想了一些办法,但是都失败了。

  • outputpublicPath,设置为函数。

结果就只能收到一个对象,里面包含了一个没啥用的hash

output: {
    filename: 'js/[name].[hash:8].bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: function (a, b) {
        console.log(a,b);
        return "//cdn/" + a.hash + "/";
    }
},

苏南大叔:webpack4系列教程,如何编写plugin处理html代码逻辑? - webpack-plugin-1
webpack4系列教程,如何编写plugin处理html代码逻辑?(图4-2)

  • MiniCssExtractPlugin.loaderpublicPath,设置为函数。

参数确实多了,不过,这个loader里面的publicPath,不是拿来设置css文件本身的地址的。而是用于处理css文件内部,引用的资源(例如图片和字体)的地址的。

{
  test: /\.css$/,
  use: [
    {
      loader: MiniCssExtractPlugin.loader,
      options: {
        publicPath: (resourcePath, context) => {
          return path.relative(path.dirname(resourcePath), context) + '/';
        },
      },
    },
    'css-loader',
  ],
},
  • 试图修改MiniCssExtractPlugin.loader

找到了一个函数,叫做mainTemplate.getAssetPath()。不会修改。

  • 试图修改HtmlWebpackPlugin

没分析出它的内部逻辑,不过在官网看到了一个hook它的html结果的例子。下面的代码是github上面的原版例子:

// If your plugin is direct dependent to the html webpack plugin:
const HtmlWebpackPlugin = require('html-webpack-plugin');
// If your plugin is using html-webpack-plugin as an optional dependency
// you can use https://github.com/tallesl/node-safe-require instead:
const HtmlWebpackPlugin = require('safe-require')('html-webpack-plugin');

class MyPlugin {
  apply (compiler) {
    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
      console.log('The compiler is starting a new compilation...')

      // Static Plugin interface |compilation |HOOK NAME | register listener 
      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
        'MyPlugin', // <-- Set a meaningful name here for stacktraces
        (data, cb) => {
          // Manipulate the content
          data.html += 'The Magic Footer'
          // Tell webpack to move on
          cb(null, data)
        }
      )
    })
  }
}

module.exports = MyPlugin

编写一个plugin

最终,苏南大叔通过编写一个基于HtmlWebpackPluginwebpackplugin,成功的分开了cssjspublicPath。虽然代码写的并不是太好。但是毕竟解决了问题。下面是一些代码要点:

  • 获得配置中的output
compilation.runtimeTemplate.outputOptions
  • 获得插件本身的options
constructor(options) {
    // console.log('插件被使用了')
    this.options = options;
}
  • 获得html
data.html

苏南大叔:webpack4系列教程,如何编写plugin处理html代码逻辑? - webpack-plugin-code
webpack4系列教程,如何编写plugin处理html代码逻辑?(图4-3)

代码如下:

newsn.net:这里是【评论】可见内容

把上边这个代码保存到plugin/test.js文件。然后调用方式就是:
webpack.config.js:

let MyPlugin = require(path.resolve(__dirname, 'plugin/test.js'));
module.exports = {
    //...
    output: {
        //...
        publicPath: "//cdn/",
    },
    plugins: [
        new MyPlugin({ publicPath: '//css.cdn/' }),
        //...
    ],
}

苏南大叔:webpack4系列教程,如何编写plugin处理html代码逻辑? - webpack-plugin-result
webpack4系列教程,如何编写plugin处理html代码逻辑?(图4-4)

相关链接

总结

虽然在本文中,苏南大叔是利用了一个replace解决了区分cssjscdn地址的需求。但是,这个插件也为苏南大叔打开了一扇门,对html模版,如果有什么不满意,就可以在这个地方进行修改了。很方便不是?

下面的地址,是苏南大叔写的webpack系列经验文章,欢迎点击:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。
本站采用创作共用版权协议, 要求署名、非商业用途和相同方式共享。
转载本站内容必须也遵循“署名-非商业用途-相同方式共享”的创作共用协议。
未经许可,规模化镜像抄袭本站内容的行为,将会根据有关法律法规进行维权。
程序如此灵动~》下所有原创文章,如被用于商业用途,请您按规定支付稿费。

 【加群】加入QQ群【175454274】和大家一起讨论这个问题

 【源码】本文代码片段及相关软件,请点此获取

 【绝密】秘籍文章入口,仅传授于有缘之人   webpack

本站的忠实读者小伙伴,正在阅读下面这些文章: