Repository navigation
Expand file tree
/
Copy pathwebpack_config.js
More file actions
180 lines (164 loc) · 5.28 KB
/
Copy pathwebpack_config.js
File metadata and controls
180 lines (164 loc) · 5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Base webpack config, shared by all packed modules
import Path from "path";
import { fileURLToPath } from 'url';
const __dirname = Path.dirname(fileURLToPath(import.meta.url));
import TerserPlugin from "terser-webpack-plugin";
import webpack from "webpack";
import { promises as fs } from "fs";
/**
* Copy a file (or directory recursively) into the dist. Used for css etc.
* that we want to copy but not bundle. I'm sure a webpack expert could do
* this a lot better!
* @param {string} from pathname to copy
* @param {string} to where to copy to
*/
function copyFile(from, to) {
const a_from = Path.normalize(Path.join(__dirname, from));
const a_to = Path.normalize(Path.join(__dirname, to));
fs.cp(a_from, a_to, {
recursive: true,
force: true,
dereference: true
})
.catch(e => {
// cp works, but throws all sorts of wierd errors for no
// apparent reason before completing.
//console.error("wierd", from, e);
});
}
/**
* Rewrite a <link> in html
* @param {string} from link to rewrite (can be a common preamble)
* @param {string} to what to replace `from` with
* @param {string} content the HTML to perform the replacement in
* @return {string} the edited HTML
*/
function relink(from, to, content) {
const re = new RegExp(`(<link[^>]*href=")${from}`, "g");
return content.replace(
re,
(m, preamble) => `${preamble}${to}`);
}
const IMPORT_MAP = {
"node_modules/knockout/build/output/knockout-latest.debug.js": {
from: "node_modules/knockout/build/output/knockout-latest.js",
to: "knockout.js"
},
"node_modules/knockout.validation/dist/knockout.validation.js": {
from: "node_modules/knockout.validation/dist/knockout.validation.min.js",
to: "knockout-validation.min.js"
},
"node_modules/bootstrap/dist/js/bootstrap.bundle.js": {
from: "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
to: "bootstrap.min.js"
},
"node_modules/bootstrap-slider/dist/bootstrap-slider.js": {
from: "node_modules/bootstrap-slider/dist/bootstrap-slider.min.js",
to: "bootstrap-slider.min.js"
},
"node_modules/clipper-lib/clipper.js": {
from: "node_modules/clipper-lib/clipper.js",
to: "clipper-lib.js"
},
"node_modules/file-saver/dist/FileSaver.js": {
from: "node_modules/file-saver/dist/FileSaver.min.js",
to: "FileSaver.min.js"
}
};
function remapImport(module) {
const map = IMPORT_MAP[module];
if (!map) throw new Error("No map for " + module);
copyFile(map.from, "dist/" + map.to);
return `<script src="${map.to}"></script>`;
}
/**
* Process one of the top level HTML files. There are a number of edits
* required for webpacking, fixing up links etc.
* @param {string} entry root name of the html file e.g. "standlone_game"
* @return {Promise} a promise that resolves when the output has been written
*/
function processHTML(entry) {
console.log(`Processing ${entry}.html`);
return fs.readFile(`./${entry}.html`)
.then(content => {
content = content.toString()
.replace(/<script type="importmap".*?<\/script>/s, "")
.replace(/(<script type="module" src=").*?"/s, '$1./SVGcut.js"')
.replace(/<script src="(.*?)".*?<\/script>/gs,
(m, p1) => remapImport(p1));
// Get CSS
copyFile("node_modules/bootstrap/dist/css/bootstrap.min.css",
"dist/bootstrap.min.css");
content = relink(
"node_modules/bootstrap/dist/css/bootstrap.css",
"bootstrap.min.css",
content);
copyFile(
"node_modules/bootstrap-slider/dist/css/bootstrap-slider.min.css",
"dist/bootstrap-slider.min.css");
content = relink(
"node_modules/bootstrap-slider/dist/css/bootstrap-slider.css",
"bootstrap-slider.min.css",
content);
copyFile("css/SVGcut.css", "dist/SVGcut.css");
content = relink("css/SVGcut.css", "SVGcut.css", content);
copyFile("images", "dist/images");
copyFile("glShaders", "dist/glShaders");
return fs.writeFile(`${__dirname}/dist/${entry}.html`, content);
});
}
fs.mkdir(`${__dirname}/dist`, { recursive: true })
.then(() => processHTML("app"));
// Webpacked code always has DISTRIBUTION
const defines = {
DISTRIBUTION: true
};
let mode = "development"; // or "production"
// --production or NODE_ENV=production will create a minimised
// production build.
if (process.env.NODE_ENV === "production") {
console.log("Production build");
mode = "production";
defines.PRODUCTION = true;
}
export default {
mode: mode, // production or development
entry: {
app: {
import: `./src/browser.js`,
filename: "SVGcut.js"
}
},
output: {
path: Path.resolve(__dirname, "./dist")
},
resolve: {
extensions: [ '.js' ],
alias: {
"gl-matrix": Path.resolve(
__dirname,
"./node_modules/gl-matrix/esm"),
"flatten-js": Path.resolve(
__dirname, "./node_modules/@flatten-js/core/dist/main.mjs")
}
},
optimization: {
// Split chunks for module reuse. Would like to use this, but it breaks.
//splitChunks: {
// chunks: "all"
//},
minimize: (mode === "production"),
minimizer: [
new TerserPlugin({
terserOptions: {
// We have to keep class names because CBOR TypeMapHandler
// uses them
keep_classnames: true
},
}),
]
},
plugins: [
new webpack.DefinePlugin(defines),
]
};