├── .npmignore
├── LICENSE.md
├── README.md
├── example
├── .babelrc
├── .gitignore
├── README.md
├── package.json
├── src
│ ├── components
│ │ └── App.tsx
│ └── index.tsx
├── tsconfig.json
├── tsconfig.legacy.json
├── webpack.config.js
├── webpack
│ ├── base.js
│ ├── dev.js
│ ├── legacyConfig.js
│ ├── multi.js
│ ├── prod.js
│ └── prod.legacy.js
└── yarn.lock
├── index.js
├── package.json
└── template.ejs
/.npmignore:
--------------------------------------------------------------------------------
1 | example/
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Tristan Teufel
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # html-webpack-multi-build-plugin
2 |
3 | This plugin simplifies the creation of script tags for module and nomodule for a webpack multi build configuration.
4 |
5 | [](http://badge.fury.io/js/html-webpack-multi-build-plugin)
6 |
7 | ### Proof of Concept
8 |
9 | Please see this project more as a proof of concept then a fully fledged solution.
10 |
11 | One day my supervisor gave me the following task:
12 | I should create a build job which creates two bundles.
13 | One bundle with polyfills for older browser, and one bundle with modern-js for newer browsers.
14 | So we researched for ways to achieve this.
15 | This respository contains a POC and all information we researched to this topic.
16 | We even successully used the plugin in a few projects.
17 |
18 | If you think something is wrong with this approach please do not hesitate to create a issue.
19 | If you have an idea how to make this better, we are very happy about any clarification or contribution.
20 | We know there are currently some down sides like the disabled preloading.
21 |
22 | ### Why do you want to do this?
23 |
24 | Most developers still transpile their code to ES5 and bundle it with polyfills to provide support for older browsers.
25 | But for newer browsers this transpiled code is unnecessary and probably slower then ES6+ code.
26 | The Idea is to create two bundles, one modern es6+ bundle and one legacy es5 bundle.
27 |
28 | ### What? How do you do that?
29 | The solution is to provide two script tags, one with type=module (es6+ code) and one with "nomodule" (es5 code).
30 | Modern Browser will now only load the script tag with type=module while legacy browser only load the script tag with "nomodule".
31 |
32 | ### Will some browser still download both bundles?
33 |
34 | Some browser like Safari, IE11, Edge are downloading both bundles, but only executing one.
35 | This plugin has integrated a clever fix for this.
36 | By creating a script tag with module / nomodule which dynamically injects the actual script tags for the javascript resources.
37 |
38 | ```
39 |
45 | ```
46 |
47 | ### Why do i need this addon?
48 | This plugin for html-webpack-plugin generates script tags for module and nomodule for a webpack multi build configuration.
49 |
50 | ### Async CSS Loading
51 | The included template add's tags for async (non blocking) css
52 | ```
53 |
54 | ```
55 |
56 | ### Read about webpack multi build configuration
57 | https://webpack.js.org/configuration/configuration-types/#exporting-multiple-configurations
58 |
59 | ### How to use this addon?
60 | Check out my [Example Project](https://github.com/firsttris/html-webpack-multi-build-plugin/tree/master/example)
61 |
62 | Summarized
63 |
64 | #### Package.json
65 | ```
66 | "scripts": {
67 | build:multi": "webpack --env.build=multi"
68 | }
69 | ```
70 |
71 | #### webpack.config
72 | ```
73 | // Legacy webpack config needs to include 'legacy'
74 | config.output.filename = '[name]_legacy.js';
75 |
76 | // Modern webpack config must not include 'legacy'
77 | config.output.filename = '[name].js';
78 |
79 | // Both webpack configs must include htmlWebpackPlugin and htmlWebpackMultiBuildPlugin
80 | const htmlWebpackMultiBuildPlugin = require('html-webpack-multi-build-plugin');
81 | const multiBuildMode = process.env.build === 'multi'
82 | const template = multiBuildMode
83 | ? require.resolve('html-webpack-multi-build-plugin/template.ejs')
84 | : require.resolve('html-webpack-plugin/default_index.ejs');
85 |
86 | config.plugins: [
87 | new htmlWebpackPlugin(
88 | {
89 | inject: !multiBuildMode,
90 | template
91 | }
92 | )
93 | new htmlWebpackMultiBuildPlugin()
94 | ]
95 | ```
96 |
97 |
98 | ### Sources
99 |
100 | https://philipwalton.com/articles/deploying-es2015-code-in-production-today/
101 | https://github.com/philipwalton/webpack-esnext-boilerplate
102 | https://jakearchibald.com/2017/es-modules-in-browsers/
103 | https://github.com/jantimon/html-webpack-plugin/issues/782
104 | https://github.com/philipwalton/webpack-esnext-boilerplate/issues/1
105 |
--------------------------------------------------------------------------------
/example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env"]
3 | }
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # dependencies
2 | node_modules/
3 | .awcache/
4 |
5 | # production
6 | build/
7 | builds/
8 | coverage/
9 | .idea/
10 | dist/
11 | dist-web/
12 | dist-electron/
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | lerna-debug.log*
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
26 | db
27 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # webpack-multi-build-example
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multi-build-starter",
3 | "version": "1.0.0",
4 | "description": "example of multi build",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --env.build=dev",
8 | "start:legacy": "webpack-dev-server --env.build=dev --env.legacy=true",
9 | "build": "webpack --env.build=prod",
10 | "build:legacy": "webpack --env.build=prod --env.legacy=true",
11 | "build:multi": "webpack --env.build=multi"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": ""
16 | },
17 | "keywords": [
18 | "wp4",
19 | "multi-build",
20 | "starter-kit",
21 | "module",
22 | "nomodule"
23 | ],
24 | "devDependencies": {
25 | "@types/react": "^16.4.6",
26 | "@types/react-dom": "^16.0.6",
27 | "babel-core": "^6.26.3",
28 | "babel-loader": "^7.1.4",
29 | "babel-polyfill": "^6.26.0",
30 | "babel-preset-env": "^1.7.0",
31 | "clean-webpack-plugin": "^0.1.19",
32 | "css-loader": "^0.28.11",
33 | "file-loader": "^1.1.11",
34 | "fork-ts-checker-webpack-plugin": "^0.4.2",
35 | "html-webpack-plugin": "^3.2.0",
36 | "html-webpack-multi-build-plugin": "firsttris/html-webpack-multi-build-plugin#master",
37 | "react": "^16.4.1",
38 | "react-dom": "^16.4.1",
39 | "react-hot-loader": "^4.3.3",
40 | "ts-loader": "^4.4.2",
41 | "typescript": "^2.9.2",
42 | "webpack": "^4.15.0",
43 | "webpack-cli": "^3.0.8",
44 | "webpack-dev-server": "^3.1.4",
45 | "webpack-merge": "^4.1.3"
46 | },
47 | "author": "tristan teufel",
48 | "license": "MIT"
49 | }
50 |
--------------------------------------------------------------------------------
/example/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export class App extends React.Component<{}, {}> {
4 | render() {
5 | return