HTML plugin webpack template content is highly customized

Time:2022-1-3

It is generally set when using HTML plugin webpacktemplateProperty to configure the HTML template. But this has disadvantages: when the team has multiple projects, the template content in HTML format can not achieve the unification of general functions and the expansion for specific projects. Therefore, if the template content is configured as JS content and the full coding ability of JS is obtained, it can encapsulate the general template content of the project in the team and ensure high customization ability

Used in this article ishtml-plugin-webpackThe version is v3. The V4 version supports more options to support the content of this article rather than through plug-ins.

The following is how to configure JS code commonly used in HTML templates

Page title

If the HTML webpack plugin is not configuredtemplateOptions, configuringtitleOption, the generated HTML file will have a title:

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      Title: 'test',
    }),
  ],
};

In the generated file:

<head>
    <meta charset="UTF-8">
    < title > test < / Title >
  </head>

Icon

set upfaviconOption, HTML plugin webpack will automatically copy the picture file tooutputDirectory, and then use it, it will be added automaticallypublicPath.

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      favicon: './build/favicon.ico',
    }),
  ],
};

In the generated HTML code:

<link rel="shortcut icon" href="https://you.com/path/to/favicon.ico">

For mobile applications, icon configuration is recommendedfavicons-webpack-plugin.

Set meta information

Many settings are usually required in HTML filesmetaInformation, via HTML webpack HTMLmetaOption to generate these meta information, such as:

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      meta: {
        Author: 'xxx front end team',
      },
    }),
  ],
};

If requiredhttp-equivRelated, the following syntax is required:

{ 
    meta: {
        pragma: { 'http-equiv': 'pragma', 'content': 'no-cache' },
    },
}

If you need tohttp-equivProperty is set more than once. It needs to be:

{ 
    meta: {
        cacheControl1: { 'http-equiv': 'cache-control', content: 'no-cache' },
        cacheControl2: { 'http-equiv': 'cache-control', content: 'no-siteapp' },
        cacheControl3: { 'http-equiv': 'cache-control', content: 'no-transform' },
    },
}

A more complete configuration:

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      meta: {
        Author: 'xxx front end team',
        cacheControl1: { 'http-equiv': 'cache-control', content: 'no-cache' },
        cacheControl2: { 'http-equiv': 'cache-control', content: 'no-siteapp' },
        cacheControl3: { 'http-equiv': 'cache-control', content: 'no-transform' },
        expires: { 'http-equiv': 'expires', content: '0' },
        compatible: { 'http-equiv': 'X-UA-Compatible', content: 'IE=edge,chrome=1' },
      },
    }),
  ],
};

Generated HTML code:

< meta name = "author" content = "XXX front end team" >
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="cache-control" content="no-siteapp">
<meta http-equiv="cache-control" content="no-transform">
<meta http-equiv="expires" content="0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

Additional resources

HTML usually requires some additional resources, such as the global provision of some libraries (jQuery, Vue)polyfillResources, etc., recommendedhtml-webpack-tags-plugin)To handle it.

HTML webpack tags plugin only adds some additional resource tags to the template, and does not do any other operations on the target resource file. It needs to be coordinatedcopy-webpack-pluginWhen used together, the copy webpack plugin can copy additional resource files (possibly in node_modules) into the webpack configurationoutputUnder the directory

Here, take the imported Google analysis file as an example, if there is a Google analysis single page application plug-in under the project root directoryautotrack:

|--assets
  |--autotrack.min.js
  |--autotrack.min.js.map

to configure:

module.exports = {
  // ...
  output: {
    // ...
    path: path.resolve(__dirname, 'dist')
  },

  plugins: [
    //You need to open the htmlwebpackplugin plug-in
    new HtmlWebpackPlugin({
      Title: 'test',
    }),
   new CopyWebpackPlugin([{
      from: './assets',
      to: './dist',
      toType: 'dir',
    }]),
    new HtmlWebpackTagsPlugin({
      tags: [{
        path: 'autotrack/autotrack.js',
        attributes: {
          async: 'true',
        },
      }],
      scripts: [{
        path: 'https://www.google-analytics.com/analytics.js',
        attributes: {
          type: 'text/javascript',
          async: 'true',
        },
        append: false,
      }],
    }),
  ],
};

Generated dist Directory:

|--dist
  |--autotrack
    |--autotrack.min.js
    |--autotrack.min.js.map
  |--bundle.js
  |--index.html

htmlCode content:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    < title > test < / Title >
  </head>
  <body>
  <script type="text/javascript" async="true"></script><script type="text/javascript"></script><script type="text/javascript" async="true"></script></body>
</html>

In addition, you can also use the enhanced library of HTML webpack tags pluginhtml-webpack-deploy-plugin

Inline JS code or other JS code directly referenced in HTML

In the actual development process, it is usually necessary tohtmlThe file contains some inline JS code or references to third-party code, such as the code for configuring Google analysis calls.

have access towebpack-concat-plugin:)) to import additional JS resources.

The advantage of webpack concat plugin over HTML webpack tags plugin is that it supports the compression of imported JS files

The webpack concat plugin will automatically copy the target JS resource to the current webpack configurationoutputDirectory, so it does not need to be used with [copy webpack plugin]

If it needs to be applied on a single pageindex.htmlImportgoogle-analytics-starter.jsContent:

;((function(){
      window.ga = window.ga || function () { (ga.q = ga.q || []).push(arguments) }; ga.l = +new Date;
      ga('create', 'UA-63187412-4', 'auto');
      ga('require', 'eventTracker');
      ga('require', 'outboundLinkTracker');
      ga('require', 'urlChangeTracker');
      ga('send', 'pageview');
})());

In this case, you need to configure the following on the webpack:

module.exports = {
  // ...
  output: {
    // ...
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new HtmlWebpackPlugin({
      Title: 'test',
    }),

    new WebpackConcatPlugin({
      uglify: false,
      sourceMap: false,
      name: 'google-analytics-starter',
      outputPath: 'static',
      fileName: '[name].[hash:8].js',
      filesToConcat: [path.resolve(__dirname, './google-analytics-starter.js')],
    }),
  ],
};

Generated HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    < title > test < / Title >
  </head>
  <body>
  <script type="text/javascript"></script><script type="text/javascript"></script></body>
</html>

For inline code, it is recommended to extract it as a JS file and reference the outer chain through webpack concat plugin For possible excessive resource requests, the webpack concat plugin can be configuredfilesToConcatFor a directory (multiple directories are OK), it will be packaged as a whole

Other logical additions

In the HTML template, you usually need to set some other content, such as DOM elements for the rendering framework to mount

<div id="app"></div>

This framework has not yet been found in the community, but you can write a simple HTML plugin webpack plug-in to implement it:

const _ = require('lodash');

function resetOptionToFn(option) {
  if (_.isArray(option)) {
    return (tags) => {
      tags.push(...option);
    };
  }
  if (_.isPlainObject(option)) {
    if (option.before || option.after) {
      return (tags) => {
        tags.unshift(...[].concat(option.before || []));
        tags.push(...[].concat(option.after || []));
      };
    }
    return (tags) => {
      tags.push(option);
    };
  }
  return () => {};
}

module.exports = class HtmlCodePlugin {
  constructor({
    body,
    head,
  } = {}) {
    this.body = resetOptionToFn(body);
    this.head = resetOptionToFn(head);
  }

  apply(_compiler) {
    const compiler = _compiler;
    compiler.hooks.compilation.tap(this.constructor.name, (compilation) => {
      compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync(this.constructor.name, async (data, cb) => {
        try {
          this.body(data.body);
          this.head(data.head);
          cb(null, data);
        } catch (error) {
          cb(error, null);
        }
      });
    });
  }
};

You can then configure the following in the webpack:

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      Title: 'test',
    }),
    new MyPlugin({
      body: {
        tagName: 'div',
        selfClosingTag: false,
        voidTag: false,
        attributes: {
          id: 'app',
        },
      },
    }),
  ],
};

Generated HTML code:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    < title > test < / Title >
  </head>
  <body>
  <script type="text/javascript"></script><div id="app"></div></body>
</html>

For other, such as comment code, ie judgment statements in HTMLif !IECan implement plug-ins similar to HTML webpack plugin.

A usable NPM library has been published in the case code:webpack-plugin-html-append-tag

Write at the end

The above lists how to configure the contents of many HTML templates with JS, which is very useful for teams building multiple projects with unified building tools Using the programming ability of JS, we can encapsulate the template configuration content commonly used by the team in the construction tool, provide API for customization of template content in the project, and provide encapsulation and extension ability

At that time, HTML plugin- [email protected] It does not support more content customization, which can only be realized through plug-ins. However, with the arrival of V4, many contents can be supported by configuring properties, and there is no need to use some plug-ins as in this article.

Recommended Today

Vue2 technology finishing 3 – Advanced chapter – update completed

3. Advanced chapter preface Links to basic chapters:https://www.cnblogs.com/xiegongzi/p/15782921.html Link to component development:https://www.cnblogs.com/xiegongzi/p/15823605.html 3.1. Custom events of components 3.1.1. Binding custom events There are two implementation methods here: one is to use v-on with vuecomponent$ Emit implementation [PS: this method is a little similar to passing from child to parent]; The other is to use ref […]