@henderea/static-site-builder 1.9.9 → 1.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/static-site-builder.js +30 -31
- package/config/cache-config.js +99 -99
- package/config/env.js +10 -11
- package/config/paths.js +55 -50
- package/config/webpack.config.dev.js +168 -168
- package/config/webpack.config.prod.js +253 -253
- package/package.json +19 -6
- package/scripts/build.js +89 -89
- package/scripts/watch.js +82 -82
- package/utils/FileSizeReporter.js +25 -25
- package/utils/checkRequiredFiles.js +5 -7
- package/utils/formatWebpackMessages.js +13 -15
- package/utils/printBuildError.js +5 -5
- package/utils/workspaceUtils.js +12 -13
|
@@ -11,50 +11,49 @@
|
|
|
11
11
|
// Makes the script crash on unhandled rejections instead of silently
|
|
12
12
|
// ignoring them. In the future, promise rejections that are not handled will
|
|
13
13
|
// terminate the Node.js process with a non-zero exit code.
|
|
14
|
-
process.on('unhandledRejection', err => {
|
|
14
|
+
process.on('unhandledRejection', (err) => {
|
|
15
15
|
throw err;
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
import spawn from 'cross-spawn';
|
|
19
19
|
const args = process.argv.slice(2);
|
|
20
20
|
|
|
21
21
|
const scriptIndex = args.findIndex(
|
|
22
|
-
x => x === 'build' || x === 'watch'
|
|
22
|
+
(x) => x === 'build' || x === 'watch'
|
|
23
23
|
);
|
|
24
24
|
const script = scriptIndex === -1 ? args[0] : args[scriptIndex];
|
|
25
25
|
const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : [];
|
|
26
26
|
|
|
27
|
-
switch
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
27
|
+
switch(script) {
|
|
28
|
+
case 'build':
|
|
29
|
+
case 'watch': {
|
|
30
|
+
const result = spawn.sync(
|
|
31
|
+
'node',
|
|
32
|
+
nodeArgs
|
|
33
|
+
.concat(require.resolve('../scripts/' + script))
|
|
34
|
+
.concat(args.slice(scriptIndex + 1)),
|
|
35
|
+
{ stdio: 'inherit' }
|
|
36
|
+
);
|
|
37
|
+
if(result.signal) {
|
|
38
|
+
if(result.signal === 'SIGKILL') {
|
|
39
|
+
console.log(
|
|
40
|
+
'The build failed because the process exited too early. ' +
|
|
41
41
|
'This probably means the system ran out of memory or someone called ' +
|
|
42
42
|
'`kill -9` on the process.'
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
);
|
|
44
|
+
} else if(result.signal === 'SIGTERM') {
|
|
45
|
+
console.log(
|
|
46
|
+
'The build failed because the process exited too early. ' +
|
|
47
47
|
'Someone might have called `kill` or `killall`, or the system could ' +
|
|
48
48
|
'be shutting down.'
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
process.exit(1);
|
|
49
|
+
);
|
|
52
50
|
}
|
|
53
|
-
process.exit(
|
|
54
|
-
break;
|
|
51
|
+
process.exit(1);
|
|
55
52
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
process.exit(result.status);
|
|
54
|
+
}
|
|
55
|
+
default:
|
|
56
|
+
console.log('Unknown script "' + script + '".');
|
|
57
|
+
console.log('Perhaps you need to update static-site-builder?');
|
|
58
|
+
break;
|
|
59
|
+
}
|
package/config/cache-config.js
CHANGED
|
@@ -1,106 +1,106 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
1
|
+
export default [
|
|
2
|
+
{
|
|
3
|
+
urlPattern: /^https:\/\/fonts\.(?:googleapis|gstatic)\.com\/.*/i,
|
|
4
|
+
handler: 'CacheFirst',
|
|
5
|
+
options: {
|
|
6
|
+
cacheName: 'google-fonts',
|
|
7
|
+
expiration: {
|
|
8
|
+
maxEntries: 4,
|
|
9
|
+
maxAgeSeconds: 365 * 24 * 60 * 60 // 365 days
|
|
11
10
|
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
urlPattern: /\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,
|
|
26
|
-
handler: 'StaleWhileRevalidate',
|
|
27
|
-
options: {
|
|
28
|
-
cacheName: 'static-image-assets',
|
|
29
|
-
expiration: {
|
|
30
|
-
maxEntries: 64,
|
|
31
|
-
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
urlPattern: /\.(?:js)$/i,
|
|
37
|
-
handler: 'StaleWhileRevalidate',
|
|
38
|
-
options: {
|
|
39
|
-
cacheName: 'static-js-assets',
|
|
40
|
-
expiration: {
|
|
41
|
-
maxEntries: 32,
|
|
42
|
-
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
urlPattern: /\.(?:css|less)$/i,
|
|
48
|
-
handler: 'StaleWhileRevalidate',
|
|
49
|
-
options: {
|
|
50
|
-
cacheName: 'static-style-assets',
|
|
51
|
-
expiration: {
|
|
52
|
-
maxEntries: 32,
|
|
53
|
-
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
54
|
-
}
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
urlPattern: /\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,
|
|
15
|
+
handler: 'StaleWhileRevalidate',
|
|
16
|
+
options: {
|
|
17
|
+
cacheName: 'static-font-assets',
|
|
18
|
+
expiration: {
|
|
19
|
+
maxEntries: 4,
|
|
20
|
+
maxAgeSeconds: 7 * 24 * 60 * 60 // 7 days
|
|
55
21
|
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
urlPattern: /\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,
|
|
26
|
+
handler: 'StaleWhileRevalidate',
|
|
27
|
+
options: {
|
|
28
|
+
cacheName: 'static-image-assets',
|
|
29
|
+
expiration: {
|
|
30
|
+
maxEntries: 64,
|
|
31
|
+
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
66
32
|
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
},
|
|
78
|
-
networkTimeoutSeconds: 10 // fall back to cache if api does not response within 10 seconds
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
urlPattern: /\.(?:js)$/i,
|
|
37
|
+
handler: 'StaleWhileRevalidate',
|
|
38
|
+
options: {
|
|
39
|
+
cacheName: 'static-js-assets',
|
|
40
|
+
expiration: {
|
|
41
|
+
maxEntries: 32,
|
|
42
|
+
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
79
43
|
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
},
|
|
91
|
-
networkTimeoutSeconds: 10 // fall back to cache if api does not response within 10 seconds
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
urlPattern: /\.(?:css|less)$/i,
|
|
48
|
+
handler: 'StaleWhileRevalidate',
|
|
49
|
+
options: {
|
|
50
|
+
cacheName: 'static-style-assets',
|
|
51
|
+
expiration: {
|
|
52
|
+
maxEntries: 32,
|
|
53
|
+
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
92
54
|
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
networkTimeoutSeconds: 10
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
urlPattern: /\.(?:json|xml|csv)$/i,
|
|
59
|
+
handler: 'NetworkFirst',
|
|
60
|
+
options: {
|
|
61
|
+
cacheName: 'static-data-assets',
|
|
62
|
+
expiration: {
|
|
63
|
+
maxEntries: 32,
|
|
64
|
+
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
104
65
|
}
|
|
105
66
|
}
|
|
106
|
-
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
urlPattern: /\/api\/.*$/i,
|
|
70
|
+
handler: 'NetworkFirst',
|
|
71
|
+
method: 'GET',
|
|
72
|
+
options: {
|
|
73
|
+
cacheName: 'apis',
|
|
74
|
+
expiration: {
|
|
75
|
+
maxEntries: 16,
|
|
76
|
+
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
77
|
+
},
|
|
78
|
+
networkTimeoutSeconds: 10 // fall back to cache if api does not response within 10 seconds
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
urlPattern: /\/api\/.*$/i,
|
|
83
|
+
handler: 'NetworkFirst',
|
|
84
|
+
method: 'POST',
|
|
85
|
+
options: {
|
|
86
|
+
cacheName: 'apis',
|
|
87
|
+
expiration: {
|
|
88
|
+
maxEntries: 16,
|
|
89
|
+
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
90
|
+
},
|
|
91
|
+
networkTimeoutSeconds: 10 // fall back to cache if api does not response within 10 seconds
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
urlPattern: /.*/i,
|
|
96
|
+
handler: 'NetworkFirst',
|
|
97
|
+
options: {
|
|
98
|
+
cacheName: 'others',
|
|
99
|
+
expiration: {
|
|
100
|
+
maxEntries: 32,
|
|
101
|
+
maxAgeSeconds: 24 * 60 * 60 // 24 hours
|
|
102
|
+
},
|
|
103
|
+
networkTimeoutSeconds: 10
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
];
|
package/config/env.js
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import paths from './paths';
|
|
10
10
|
|
|
11
11
|
// Make sure that including paths.js after env.js will read .env variables.
|
|
12
12
|
delete require.cache[require.resolve('./paths')];
|
|
13
13
|
|
|
14
14
|
const NODE_ENV = process.env.NODE_ENV;
|
|
15
|
-
if
|
|
15
|
+
if(!NODE_ENV) {
|
|
16
16
|
throw new Error(
|
|
17
17
|
'The NODE_ENV environment variable is required but was not specified.'
|
|
18
18
|
);
|
|
@@ -34,8 +34,8 @@ var dotenvFiles = [
|
|
|
34
34
|
// that have already been set. Variable expansion is supported in .env files.
|
|
35
35
|
// https://github.com/motdotla/dotenv
|
|
36
36
|
// https://github.com/motdotla/dotenv-expand
|
|
37
|
-
dotenvFiles.forEach(dotenvFile => {
|
|
38
|
-
if
|
|
37
|
+
dotenvFiles.forEach((dotenvFile) => {
|
|
38
|
+
if(fs.existsSync(dotenvFile)) {
|
|
39
39
|
require('dotenv-expand')(
|
|
40
40
|
require('dotenv').config({
|
|
41
41
|
path: dotenvFile,
|
|
@@ -56,17 +56,17 @@ dotenvFiles.forEach(dotenvFile => {
|
|
|
56
56
|
const appDirectory = fs.realpathSync(process.cwd());
|
|
57
57
|
process.env.NODE_PATH = (process.env.NODE_PATH || '')
|
|
58
58
|
.split(path.delimiter)
|
|
59
|
-
.filter(folder => folder && !path.isAbsolute(folder))
|
|
60
|
-
.map(folder => path.resolve(appDirectory, folder))
|
|
59
|
+
.filter((folder) => folder && !path.isAbsolute(folder))
|
|
60
|
+
.map((folder) => path.resolve(appDirectory, folder))
|
|
61
61
|
.join(path.delimiter);
|
|
62
62
|
|
|
63
63
|
// Grab NODE_ENV and SSB_APP_* environment variables and prepare them to be
|
|
64
64
|
// injected into the application via DefinePlugin in Webpack configuration.
|
|
65
65
|
const ALLOWED_ENV = /^(SSB_APP_|VERCEL_|NOW_)/i;
|
|
66
66
|
|
|
67
|
-
function getClientEnvironment(publicUrl) {
|
|
67
|
+
export default function getClientEnvironment(publicUrl) {
|
|
68
68
|
const raw = Object.keys(process.env)
|
|
69
|
-
.filter(key => ALLOWED_ENV.test(key))
|
|
69
|
+
.filter((key) => ALLOWED_ENV.test(key))
|
|
70
70
|
.reduce(
|
|
71
71
|
(env, key) => {
|
|
72
72
|
env[key] = process.env[key];
|
|
@@ -94,4 +94,3 @@ function getClientEnvironment(publicUrl) {
|
|
|
94
94
|
return { raw, stringified };
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
module.exports = getClientEnvironment;
|
package/config/paths.js
CHANGED
|
@@ -6,35 +6,35 @@
|
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import url from 'url';
|
|
12
|
+
import { findMonorepo } from '../utils/workspaceUtils';
|
|
13
13
|
|
|
14
14
|
// Make sure any symlinks in the project folder are resolved:
|
|
15
15
|
// https://github.com/facebookincubator/create-react-app/issues/637
|
|
16
16
|
const appDirectory = fs.realpathSync(process.cwd());
|
|
17
|
-
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
|
|
17
|
+
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
|
|
18
18
|
|
|
19
19
|
const resolveAppFirst = (...paths) => {
|
|
20
|
-
|
|
21
|
-
}
|
|
20
|
+
return resolveApp(paths.find((e) => fs.existsSync(resolveApp(e))) || paths[0]);
|
|
21
|
+
};
|
|
22
22
|
|
|
23
23
|
const envPublicUrl = process.env.PUBLIC_URL;
|
|
24
24
|
|
|
25
25
|
function ensureSlash(path, needsSlash) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
const hasSlash = path.endsWith('/');
|
|
27
|
+
if(hasSlash && !needsSlash) {
|
|
28
|
+
return path.substr(path, path.length - 1);
|
|
29
|
+
} else if(!hasSlash && needsSlash) {
|
|
30
|
+
return `${path}/`;
|
|
31
|
+
} else {
|
|
32
|
+
return path;
|
|
33
|
+
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const getPublicUrl = appPackageJson =>
|
|
37
|
-
|
|
36
|
+
const getPublicUrl = (appPackageJson) =>
|
|
37
|
+
envPublicUrl || require(appPackageJson).homepage;
|
|
38
38
|
|
|
39
39
|
// We use `PUBLIC_URL` environment variable or "homepage" field to infer
|
|
40
40
|
// "public path" at which the app is served.
|
|
@@ -43,53 +43,58 @@ const getPublicUrl = appPackageJson =>
|
|
|
43
43
|
// We can't use a relative path in HTML because we don't want to load something
|
|
44
44
|
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
|
|
45
45
|
function getServedPath(appPackageJson) {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
const publicUrl = getPublicUrl(appPackageJson);
|
|
47
|
+
const servedUrl =
|
|
48
48
|
envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');
|
|
49
|
-
|
|
49
|
+
return ensureSlash(servedUrl, true);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const resolveOwn = relativePath => path.resolve(__dirname, '..', relativePath);
|
|
52
|
+
const resolveOwn = (relativePath) => path.resolve(__dirname, '..', relativePath);
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
54
|
+
export const dotenv = resolveApp('.env');
|
|
55
|
+
export const ssbConfig = resolveApp('static-site-builder.config.js');
|
|
56
|
+
export const publicDir = resolveApp('public');
|
|
57
|
+
export const tsConfig= resolveApp('tsconfig.json');
|
|
58
|
+
export const appPath= resolveApp('.');
|
|
59
|
+
export const appBuild= resolveApp('build');
|
|
60
|
+
export const appDist= resolveApp('dist');
|
|
61
|
+
export const appTemplate= resolveAppFirst('src/index.html', 'src/index.ejs', 'src/index.hbs');
|
|
62
|
+
export const appIndex= resolveAppFirst('src/index.js', 'src/index.ts');
|
|
63
|
+
export const appPackageJson= resolveApp('package.json');
|
|
64
|
+
export const appSrc= resolveApp('src');
|
|
65
|
+
export const testsSetup= resolveApp('src/setupTests.js');
|
|
66
|
+
export const appNodeModules= resolveApp('node_modules');
|
|
67
|
+
export const publicUrl= getPublicUrl(resolveApp('package.json'));
|
|
68
|
+
export const servedPath= getServedPath(resolveApp('package.json'));
|
|
69
|
+
export const ownPath= resolveOwn('.');
|
|
70
|
+
export const ownNodeModules= resolveOwn('node_modules');
|
|
71
|
+
export {
|
|
72
|
+
resolveApp,
|
|
73
|
+
resolveAppFirst,
|
|
74
|
+
resolveOwn,
|
|
75
|
+
ensureSlash
|
|
76
76
|
};
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
const srcPaths = [module.exports.appSrc];
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
let useYarn = fs.existsSync(
|
|
82
82
|
path.join(module.exports.appPath, 'yarn.lock')
|
|
83
83
|
);
|
|
84
84
|
|
|
85
85
|
let checkForMonorepo = true;
|
|
86
86
|
|
|
87
|
-
if
|
|
87
|
+
if(checkForMonorepo) {
|
|
88
88
|
// if app is in a monorepo (lerna or yarn workspace), treat other packages in
|
|
89
89
|
// the monorepo as if they are app source
|
|
90
90
|
const mono = findMonorepo(appDirectory);
|
|
91
|
-
if
|
|
92
|
-
Array.prototype.push.apply(
|
|
91
|
+
if(mono.isAppIncluded) {
|
|
92
|
+
Array.prototype.push.apply(srcPaths, mono.pkgs);
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
}
|
|
94
|
+
useYarn = module.exports.useYarn || mono.isYarnWs;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
srcPaths,
|
|
99
|
+
useYarn
|
|
100
|
+
};
|