Skip to content

Instantly share code, notes, and snippets.

@uhop
Last active April 29, 2021 12:19
Show Gist options
  • Save uhop/7f3d756e5f9e04c607486c95fd3d31a5 to your computer and use it in GitHub Desktop.
Save uhop/7f3d756e5f9e04c607486c95fd3d31a5 to your computer and use it in GitHub Desktop.
Modern/legacy builds with webpack
'use strict';
if (process.argv.length < 3) {
console.log('Usage: node build-index.js inFile outFile');
console.log(' All file names are relative to the project directory.')
console.log('Example: node build-index.js src/index.html docs/index.html');
process.exit(1);
}
const fs = require('fs');
const path= require('path');
const lodash = require('lodash'); // already pulled in by dev dependencies
const projectDir = path.join(__dirname, '/../');
process.chdir(projectDir);
const tmpl = fs.readFileSync(path.normalize(process.argv[2]), {encoding: 'utf8'});
const result = lodash.template(tmpl, {variable: 'require'})(require);
fs.writeFileSync(path.normalize(process.argv[3]), result);
{
"scripts": {
"start": "webpack-dev-server --config ./webpack.dev.config.js --color --mode development --hot --history-api-fallback --open",
"build-dev": "webpack --config ./webpack.dev.config.js --mode development --profile --json > stats.json",
"build-app": "webpack --config ./webpack.config.js --mode production --profile --json > stats.json",
"build-index": "node build-scripts/build-index.js src/index.html dist/index.html",
"build": "npm run build-app && npm run build-index"
}
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href=".<%= htmlWebpackPlugin.files.chunks.modern.css %>" />
<script>
window.APP_CONFIG = {
editor: {
css: "<%= htmlWebpackPlugin.files.chunks['modern-editor'].css %>",
'modern-js': "<%= htmlWebpackPlugin.files.chunks['modern-editor'].entry %>",
'legacy-js': ''
},
viewer: {
css: '',
'modern-js': "<%= htmlWebpackPlugin.files.chunks['modern-viewer'].entry %>",
'legacy-js': ''
}
};
</script>
<script type="module" src=".<%= htmlWebpackPlugin.files.chunks.modern.entry %>"></script>
</head>
<body>
<main id="app"></main>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<% const fs = require('fs'); const files = fs.readdirSync('./dist'); %>
<link rel="stylesheet" href="./<%= files.filter(name => /^modern\..*\.css$/.test(name))[0] %>" />
<script>
window.APP_CONFIG = {
editor: {
css: '/<%= files.filter(name => /^modern-editor\..*\.css$/.test(name))[0] %>',
'modern-js': '/<%= files.filter(name => /^modern-editor\..*\.js$/.test(name))[0] %>',
'legacy-js': '/<%= files.filter(name => /^legacy-editor\..*\.js$/.test(name))[0] %>'
},
viewer: {
css: '',
'modern-js': '/<%= files.filter(name => /^modern-viewer\..*\.js$/.test(name))[0] %>',
'legacy-js': '/<%= files.filter(name => /^legacy-viewer\..*\.js$/.test(name))[0] %>'
}
};
</script>
<script type="module" src="./<%= files.filter(name => /^modern\..*\.js$/.test(name))[0] %>"></script>
<script nomodule src="./<%= files.filter(name => /^legacy\..*\.js$/.test(name))[0] %>"></script>
</head>
<body>
<main id="app"></main>
</body>
</html>
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const Visualizer = require('webpack-visualizer-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const modernConfig = {
entry: {modern: './src/index.js', 'modern-editor': './src/editor/editor.js', 'modern-viewer': './src/editor/viewer.js'},
module: {
rules: [
{
test: /\.jsx?$/,
use: {
loader: 'babel-loader',
options: {
babelrc: false,
sourceType: 'unambiguous',
presets: [
[
'@babel/env',
{
modules: false,
loose: true,
useBuiltIns: 'usage',
targets: {
browsers: ['Chrome >= 60', 'Safari >= 10.1', 'iOS >= 10.3', 'Firefox >= 54', 'Edge >= 15']
}
}
],
'@babel/react'
],
plugins: [
['@babel/plugin-proposal-class-properties', {loose: true}],
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-proposal-throw-expressions'
]
}
},
exclude: /\b(?:core-js|prop-types|react-enroute|custom-elements-polyfill)\b/
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
react: 'preact-compat',
'react-dom': 'preact-compat',
components: __dirname + '/src/components/',
configs: __dirname + '/src/configs/',
utils: __dirname + '/src/utils/'
}
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: '[name].[contenthash].js'
},
plugins: [
new CleanWebpackPlugin('dist', {}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
chunkFilename: '[id].[hash].css'
}),
new WebpackMd5Hash(),
new CopyWebpackPlugin(['./static']),
new OptimizeCssAssetsPlugin(),
new Visualizer({filename: './statistics-modern.html'})
],
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
minChunks: 1,
enforce: true
}
}
}
}
};
const legacyConfig = {
entry: {legacy: './src/index.js', 'legacy-editor': './src/editor/editor.js', 'legacy-viewer': './src/editor/viewer.js'},
module: {
rules: [
{
test: /\.jsx?$/,
use: {
loader: 'babel-loader',
options: {
babelrc: false,
sourceType: 'unambiguous',
presets: [
[
'@babel/env',
{
modules: false,
loose: true,
useBuiltIns: 'usage',
targets: {
browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']
}
}
],
'@babel/react'
],
plugins: [
['@babel/plugin-proposal-class-properties', {loose: true}],
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-proposal-throw-expressions'
]
}
},
exclude: /\b(?:core-js|prop-types|react-enroute|custom-elements-polyfill)\b/
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
react: 'preact-compat',
'react-dom': 'preact-compat',
components: __dirname + '/src/components/',
configs: __dirname + '/src/configs/',
utils: __dirname + '/src/utils/'
}
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: '[name].[contenthash].js'
},
plugins: [new Visualizer({filename: './statistics-legacy.html'})],
optimization: {
minimizer: [
new UglifyJsPlugin({
sourceMap: false,
parallel: true,
uglifyOptions: {
compress: {inline: false},
output: {
comments: false,
beautify: false,
preserve_line: false,
semicolons: false,
indent_level: 0,
indent_start: 0
}
}
})
]
}
};
module.exports = [modernConfig, legacyConfig];
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
module.exports = {
entry: {modern: './src/index.js', 'modern-editor': './src/editor/editor.js', 'modern-viewer': './src/editor/viewer.js'},
module: {
rules: [
{
test: /\.jsx?$/,
use: {
loader: 'babel-loader',
options: {
babelrc: false,
sourceType: 'unambiguous',
presets: [
[
'@babel/env',
{
modules: false,
useBuiltIns: 'usage',
targets: {
browsers: ['Chrome >= 60', 'Safari >= 10.1', 'iOS >= 10.3', 'Firefox >= 54', 'Edge >= 15']
}
}
],
'@babel/react'
],
plugins: [
['@babel/plugin-proposal-class-properties', {loose: true}],
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-proposal-throw-expressions'
]
}
},
exclude: /\b(?:core-js|prop-types|react-enroute|custom-elements-polyfill)\b/
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
react: 'preact-compat',
'react-dom': 'preact-compat',
components: __dirname + '/src/components/',
configs: __dirname + '/src/configs/',
utils: __dirname + '/src/utils/'
}
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: '[name].js'
},
plugins: [
new CleanWebpackPlugin('./dist', {}),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
new HtmlWebpackPlugin({
inject: false,
// hash: true,
template: './src/index-dev.html',
filename: 'index.html'
}),
new WebpackMd5Hash(),
new CopyWebpackPlugin(['./static'])
],
devServer: {
headers: {'Access-Control-Allow-Origin': '*'}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment