{"id":14976341,"url":"https://github.com/lcxfs1991/html-res-webpack-plugin","last_synced_at":"2025-04-06T20:09:31.828Z","repository":{"id":3388583,"uuid":"49323219","full_name":"lcxfs1991/html-res-webpack-plugin","owner":"lcxfs1991","description":"plugin for generating html in webpack","archived":false,"fork":false,"pushed_at":"2022-12-07T17:33:39.000Z","size":1636,"stargazers_count":167,"open_issues_count":15,"forks_count":34,"subscribers_count":12,"default_branch":"v4","last_synced_at":"2025-03-28T00:45:45.529Z","etag":null,"topics":["chunk","html","html-files","html-webpack-plugin","webpack","webpack-plugin","webpack2"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lcxfs1991.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-09T12:18:58.000Z","updated_at":"2024-04-16T07:13:34.000Z","dependencies_parsed_at":"2023-01-13T12:28:46.539Z","dependency_job_id":null,"html_url":"https://github.com/lcxfs1991/html-res-webpack-plugin","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcxfs1991%2Fhtml-res-webpack-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcxfs1991%2Fhtml-res-webpack-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcxfs1991%2Fhtml-res-webpack-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcxfs1991%2Fhtml-res-webpack-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lcxfs1991","download_url":"https://codeload.github.com/lcxfs1991/html-res-webpack-plugin/tar.gz/refs/heads/v4","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247543589,"owners_count":20955865,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chunk","html","html-files","html-webpack-plugin","webpack","webpack-plugin","webpack2"],"created_at":"2024-09-24T13:53:45.030Z","updated_at":"2025-04-06T20:09:31.810Z","avatar_url":"https://github.com/lcxfs1991.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# html-res-webpack-plugin\n\n[![NPM Version](https://img.shields.io/npm/v/html-res-webpack-plugin.svg?style=flat)](https://www.npmjs.com/package/html-res-webpack-plugin)\n[![Travis](https://img.shields.io/travis/lcxfs1991/html-res-webpack-plugin.svg)](https://travis-ci.org/lcxfs1991/html-res-webpack-plugin)\n[![AppVeyor](https://img.shields.io/appveyor/ci/lcxfs1991/html-res-webpack-plugin.svg)](https://ci.appveyor.com/project/lcxfs1991/html-res-webpack-plugin)\n[![Deps](https://david-dm.org/lcxfs1991/html-res-webpack-plugin.svg)](https://david-dm.org/lcxfs1991/html-res-webpack-plugin)\n\n### [中文文档](/README_ZH.md)\n\n## Why do I rewrite the whole thing\n\nI rencently notice that webpack is based itself on chunks. Therefore, writing plugin logic based on chunk may be adaptable to the core and sprite of webpack.\n\n## Basic Concpets: `chunks` and `assets`\n\nIn webpack, the basic element is `chunks`. The values in `entry` of webpack config are `chunks`. For instance, `index` and `detail` in the following entry config are chunks' names; In most cases, chunk is a js file. But if you require stylesheet or other files in js, a js chunk will include not only js file but also the files you require.\n\n```javascript\nentry: {\n  index: xxx;\n  detail: xxx;\n}\n```\n\nWhat about assets? Assets are files will be exported by webpack. They can be any file types like stylesheets, images, html and so on.\n\n## Breaking Change For V3\n\nSince V3, we must add extension for both `default` or `html` mode. Otherwise, it will prompt an error.\n\n## Require html-loader\n\n[html-loader](https://github.com/webpack/html-loader) is required after `v1.1.3`, an example option is as follows:\n\n```javascript\nrules: [\n  // some other loaders\n  {\n    test: /\\.html$/,\n    loader: \"html-loader\"\n  }\n];\n```\n\n## How to start\n\nsrc/index.html\n--\u003e\ndist/index.html\n\n```javascript\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\" id=\"html\"\u003e\n\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003cmeta http-equiv=\"x-dns-prefetch-control\" content=\"on\" /\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no, minimal-ui\" /\u003e\n    \u003ctitle\u003ehtml-res-webpack-example\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cdiv class=\"preview-wrapper\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nsrc/page/preview/main.js\n--\u003e\ndist/js/preview/preview.js\n\n```javascript\nrequire(\"./index.scss\");\n\nvar init = function() {\n  // some code here\n};\n```\n\nsrc/page/preview/index.scss\n--\u003e\ndist/css/preview/preview.css\n\n```javascript\nhtml, body {\n    margin: 0;\n}\n// some code here\n```\n\nwebpack.config.js\n\n```javascript\n    var config = {\n        hash: \"-[hash:6]\",\n        chunkhash: \"-[chunkhash:6]\",\n        contenthash: \"-[contenthash:6]\"\n    };\n    var webpackconfig = {\n        entry: {\n            'preivew/preview': [path.join(config.path.src, \"/page/preview/main.js\")],\n        },\n\n        /**\n         *  webpack options below\n         */\n        .\n        .\n        .\n        output: {\n            publicPath: (config.env === 'prod') ? config.cdn : config.defaultPath,\n            path: path.join(config.path.dist),\n            filename: \"js/[name]\" + config.chunkhash + \".js\"\n        },\n\n        .\n        .\n        .\n\n        plugins: [\n            // some other plugins\n            new ExtractTextPlugin(\"./css/[name]\" + config.contenthash + \".css\"),\n            new HtmlResWebpackPlugin({\n                filename: \"index.html\",\n                template: \"src/index.html\",\n                chunks:{\n                    'index.js': {\n                        attr: 'async=\"true\"',  // attributes for js file in index chunk\n                        inline: true,                   // inline or not for index chunk\n                    },\n                    'index.css': {\n                        attr: \"offline\",  // attributes for css file in index chunk\n                    }\n                },\n            });\n        ]\n    };\n```\n\npackage.json\n\n```javascript\n\"scripts\": {\n    \"dev\": \"webpack --progress --colors --watch\",\n    \"publish-mac\": \"export NODE_ENV=prod\u0026\u0026webpack -p --progress --colors\",\n    \"publish-windows\": \"SET NODE_ENV=prod\u0026\u0026webpack -p --progress --colors\"\n },\n```\n\nOne thing need to be noticed is `hash` and `chunkhash`. The difference between `hash` and `chunkhash` is that `hash` is the same for all resources and `chunkhash` is different for specific resource. Usually you are recommended to use `chunkhash` instead (Exception for style files required in an entry js file. They share the same `chunkhash` if you use extract-text-webpack-plugin. Please use `contenthash` instead in order to ensure hash for stylesheet changes only when content changes).\n\nAnother thing worth being noticed is the order of `chunks`. The order of resources that will be injected is based on the order of `chunks` in `html-res-webpack-plugin`.\n\n## Inject External Resource\n\nSometimes, you may need to use external common resources. If this is the case, please write options like following:\n\n```javascript\nchunks:{\n    'qreport': {\n        external: true,                                 // tell the plugin not to append publicPath\n        res:  \"//s.url.cn/pub/js/qreport.js?_bid=2231\", // resource path\n        attr: 'async=\"true\"',\n    }\n}\n```\n\n## Multiple Html Page\n\nSometimes there are more than one html pages in your projects. In this situation, please use similar iteration code to add plugins for different html pages\n\n```javascript\nvar config = {\n  hash: \"-[hash:6]\",\n  chunkhash: \"-[chunkhash:6]\",\n  contenthash: \"-[contenthash:6]\"\n};\n\nvar route = [\"index\", \"detail\"];\n\nvar webapckConfig = {\n  entry: {\n    \"js/index\": \"xxx/index\",\n    \"js/detail\": \"xxx/detail\"\n  }\n};\n\nlet pageMapping = {\n  detail: {\n    \"js/detail.js\": {\n      attr: \"\"\n    },\n    \"js/detail.css\": {\n      attr: \"\"\n    }\n  },\n  index: {\n    \"js/index.js\": {\n      attr: \"\"\n    },\n    \"js/index.css\": {\n      attr: \"\"\n    }\n  }\n};\n\nwebpackConfig.addPlugins = function(plugin, opt) {\n  devConfig.plugins.push(new plugin(opt));\n};\n\nroute.html.forEach(function(page) {\n  webapckConfig.addPlugins(HtmlResWebpackPlugin, {\n    filename: page + \".html\",\n    template: \"src/\" + page + \".html\",\n    favicon: \"src/favicon.ico\",\n    chunks: pageMapping[page]\n  });\n});\n```\n\n## Favicon\n\nwebpack.config.js\n\n```javascript\nnew HtmlResWebpackPlugin({\n    filename: \"index.html\",\n    template: \"xxx/index.html\",\n    favicon: \"xxx/favicon.ico\",\n    chunks:[\n        'js/index.js',\n        'js/index.css',\n    ],\n}),\n```\n\n## Modify Html Content Before Output\n\n```javascript\nnew HtmlResWebpackPlugin({\n    filename: \"index.html\",\n    template: \"src/index.html\",\n    templateContent: function(tpl) {\n        // some modification of tpl\n        // you can use this.options [user input plugin options]\n        // and this.webpackOptions [webpack config] here, you can open index.js of the plugin\n        // to check what options are offered\n        return tpl;\n    }\n}),\n```\n\n## Support Writing Assets in html files\n\nIn version 0.0.7 and before, we support writing assets in html files which is intuitive for developers. We drop this feature in v1.0 but not it is back in v1.1 but there are a few differences.\n\nFor example, if the config for entry is like following:\n\n```javascript\nentry: {\n    'index': xxx,\n    'detail': xxx,\n    'libs/react': xxx,\n}\n```\n\nThen, the settings for assets in html can be like this. That is to say, we put the key value of entry in asset route in order for the plugin to replace with the correct value for convenience.\n\n```javascript\n\u003cscript src=\"libs/react.js\"\u003e\u003c/script\u003e\n\u003clink rel=\"stylesheet\" href=\"index.css\"\u003e\n\u003cscript src=\"index.js\"\u003e\u003c/script\u003e\n```\n\nIf you hope to add attribute to the resource, please add it right before `src` or `rel`.\n\n```javascript\n\u003cscript asycn defer src=\"libs/react.js\"\u003e\u003c/script\u003e\n\u003clink asycn defer rel=\"stylesheet\" href=\"index.css\"\u003e\n```\n\nBut for favico, we can directly write like this:\n\n```javascript\n\u003clink rel=\"shortcut icon\" type=\"image/x-icon\" href=\"favicon.ico\"\u003e\n\u003clink rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\"\u003e\n```\n\nIf you have no idea about the chunk name, you can try running webpack, the plugin will print chunk names available for usage.\n\n```javascript\n=====html-res-webapck-plugin=====\nchunk1: commons.js\nchunk2: js/index.js\nchunk3: js/index.css\nchunk4: js/list.js\nchunk5: js/list.css\nchunk6: js/detail.js\nchunk7: js/detail.css\nchunk8: libs/react\n```\n\nIf you wanna inline resources that webpack will not compile, you can either make it through `copy-webpack-plugin-hash` (mentioned in next section) or make it through the plugin. For example, if the project structure is like this:\n\n```javascript\n-- src\n  |-- index.html\n  |-- libs\n  |    |-- react.js\n  |-- css\n  |    |-- index.css\n```\n\nThen, you can write the resource matching in `index.html` like following:\n\n```html\n\u003cscript asycn defer src=\"./libs/react.js?__inline\"\u003e\u003c/script\u003e\n\u003clink asycn defer rel=\"stylesheet\" href=\"./css/index.css?__inline\"\u003e\n```\n\nIf you only hope to show certain asset in production environment, you can set `env` options to `production`, then write the resource like following:\n\n```html\n\u003cscript asycn defer src=\"./libs/react.js?__production\"\u003e\u003c/script\u003e\n\u003clink asycn defer rel=\"stylesheet\" href=\"./css/index.css?__production\"\u003e\n```\n\nSame as asset in development environment:\n\n```html\n\u003cscript asycn defer src=\"./libs/react.js?__development\"\u003e\u003c/script\u003e\n\u003clink asycn defer rel=\"stylesheet\" href=\"./css/index.css?__development\"\u003e\n```\n\n## Usage with `copy-webpack-plugin-hash`\n\n[copy-webpack-plugin-hash](https://www.npmjs.com/package/copy-webpack-plugin-hash) is a plugin that helps copy files directly without webpack parsing. I add `namePattern` option feature for it so that files generated by this plugin can also have hash (Once the main repo accepts my pull request, I will delete this temporary repo).\n\nIf you use copy-webpack-plugin for example, you can use `html-res-webpack-plugin` easily. For example, if you copy `/xxx/libs` folder to `libs/`. If the folder contains `react` and `react-dom`, you can add chunks `libs/react.js` and `libs/react-dom.js` in `html-res-webpack-plugin`.\n\n```javascript\n// copy-webpack-plugin-hash@5.x and 6.x\nplugins: [\n  new CopyWebpackPlugin(\n    [\n      {\n        from: \"/xxx/libs/\",\n        to: \"libs/\"\n      }\n    ],\n    {\n      namePattern: \"[name]-[contenthash:6].js\"\n    }\n  ),\n  new HtmlResWebpackPlugin({\n    filename: \"index.html\",\n    template: config.path.src + \"/resource-copy-plugin-1/index.html\",\n    chunks: [\n      \"libs/react.js\",\n      \"libs/react-dom.js\",\n      \"js/index.js\",\n      \"js/index.css\"\n    ]\n  })\n];\n\n// copy-webpack-plugin-hash@5.x and 6.x\nplugins: [\n  new CopyWebpackPlugin([\n    {\n      from: \"/xxx/libs/\",\n      to: \"libs/[name]-[hash:6].[ext]\"\n    }\n  ]),\n  new HtmlResWebpackPlugin({\n    filename: \"index.html\",\n    template: config.path.src + \"/resource-copy-plugin-1/index.html\",\n    chunks: [\n      \"libs/react.js\",\n      \"libs/react-dom.js\",\n      \"js/index.js\",\n      \"js/index.css\"\n    ]\n  })\n];\n```\n\nIf you prefer writing assets in html files, it works too! Each file copied by the plugin will be regarded as a chunk, like `libs/react.js`, `libs/react-dom.js`, `js/index.js`. You can use these chunk names for `html-res-webpack-plugin` to match resource in html files which makes you easier to inline or md5 resources.\n\n## Options\n\n* `mode`:\n  * is optional\n  * `default` (write assets in config `chunks`) | `html` (write assets in html)\n* `env`\n  * is optional\n  * `production` (production env) | `development` (development env, not inline resource)\n  * default `production`\n* `filename`:\n  * is required\n  * generated filename\n* `template`:\n  * is required\n  * template source\n* `entryLog`:\n  * is optional\n  * [Boolean]\n  * default `true`, if you use `html` `mode`, you can enable this to show entry names and use example\n* `removeUnMatchedAssets`:\n  * is optional\n  * not recommended anymore\n  * [Boolean]\n  * default `false`, this is a beta option, which is used for remove asset if it is not found.\n* `logLevel`:\n  * is optional\n  * [Integer]\n  * default `0`, 0 =\u003e info(green), 1 =\u003e alert(yellow)\n* `chunks`:\n  * is required if `mode` is `default`, is not required if `mode` is `html`\n  * [Array|Object]\n  * injected chunks\n  * examples:\n\n[Array]\n\n```javascript\n    entry: {\n        'index': xxx,\n        'detail': xxx,\n        'libs/react': xxx,\n    }\n\n    plugins: [\n        new HtmlResWebpackPlugin({\n            /** other config */\n            chunks: [\n                'index.js',\n                'index.css',\n                'detail.js',\n                'detail.css',\n                'libs/react.js'\n            ]\n        })\n    ]\n```\n\n[Object]\n\n```javascript\n    plugins: [\n        new HtmlResWebpackPlugin({\n            /** other config */\n            chunks: {\n                'qreport.js': {\n                    external: true              // tell the plugin not to append publicPath\n                    res: \"xxx\"                  // resource path\n                },\n                'index.js': {\n                    attr: {\n                        js: 'async=\"true\"',    // attributes for js file in index chunk\n                        css: \"offline\",\n                    },\n                },\n                'index.css': {\n                    attr: \"offline\",    // attributes for css file in index chunk\n                },\n                'detail.js': {\n                    inline: true,                 // inline or not for js file in detail chunk\n                },\n                'detail.css': {\n                    inline: true,                 // inline or not for css file in detail chunk\n                },\n                'libs/react.js': nulls\n            }\n        })\n    ]\n```\n\n* `htmlMinify`:\n  * is optional\n  * please checkout [html-minifier](https://github.com/kangax/html-minifier) to see detail options. If set false | null, html files won't be compressed.\n* `favicon`:\n  * is optional\n  * favicon path, for example, \"src/favicon.ico\"\n* `templateContent`:\n  * is optional\n  * a point for developer to modify html content before output. `this.options` and `this.webpackOptions`can be used in such a function.\n* `cssPublicPath`:\n  * is optional\n  * pubilc path for css, using webpack config `output.publicPath` for default\n\n## Last Words\n\nI add automatic testing samples fo for the plugin to ensure stablity and relablility. I starting using this plugin in internal development.\n\nIf you still don't understand README, you can checkout examples in specWepback where testing samples are located.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flcxfs1991%2Fhtml-res-webpack-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flcxfs1991%2Fhtml-res-webpack-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flcxfs1991%2Fhtml-res-webpack-plugin/lists"}