Skip to content

Commit e19ceb0

Browse files
authored
Chore: Backport recent refactorings (#1648)
1 parent e98994a commit e19ceb0

27 files changed

+231
-214
lines changed

.changeset/silver-taxis-sparkle.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'preact-cli': patch
3+
---
4+
5+
Ensures the public path is normalized when registering service workers

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
**/node_modules
22
**/tests/output
3+
**/*.d.ts

.eslintrc

+1-9
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,5 @@
4040
"react/jsx-no-undef": 2,
4141
"react/jsx-uses-react": 2,
4242
"react/jsx-uses-vars": 2
43-
},
44-
"overrides": [
45-
{
46-
"files": ["**/*.ts"],
47-
"rules": {
48-
"no-undef": "off"
49-
}
50-
}
51-
]
43+
}
5244
}

jsconfig.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ESNext",
4+
"moduleResolution": "Node",
5+
"allowJs": true,
6+
"checkJs": true,
7+
"noEmit": true,
8+
"resolveJsonModule": true,
9+
"allowSyntheticDefaultImports": true,
10+
"jsx": "react",
11+
"jsxFactory": "h",
12+
"jsxFragmentFactory": "Fragment"
13+
},
14+
"include": ["packages/**/*"]
15+
}

packages/cli/global.d.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
declare global {
2+
const __webpack_public_path__: string;
3+
namespace jest {
4+
interface Matchers<R> {
5+
toBeCloseInSize(receivedSize: number, expectedSize: number): R;
6+
toFindMatchingKey(receivedKey: string): R;
7+
}
8+
}
9+
}
10+
11+
export {};

packages/cli/lib/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const envinfo = require('envinfo');
33
const sade = require('sade');
44
const notifier = require('update-notifier');
55
const { error } = require('./util');
6-
const pkg = require('../package');
6+
const pkg = require('../package.json');
77

88
const ver = process.version;
99
const min = pkg.engines.node;
@@ -12,7 +12,7 @@ if (
1212
.substring(1)
1313
.localeCompare(min.match(/\d+/g).join('.'), 'en', { numeric: true }) === -1
1414
) {
15-
return error(
15+
error(
1616
`You are using Node ${ver} but preact-cli requires Node ${min}. Please upgrade Node to continue!`,
1717
1
1818
);

packages/cli/lib/lib/constants.js

-5
This file was deleted.

packages/cli/lib/lib/entry.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,19 @@ if (process.env.NODE_ENV === 'development') {
1313

1414
// only add a debug sw if webpack service worker is not requested.
1515
if (process.env.ADD_SW === undefined && 'serviceWorker' in navigator) {
16-
// eslint-disable-next-line no-undef
17-
navigator.serviceWorker.register(__webpack_public_path__ + 'sw-debug.js');
16+
navigator.serviceWorker.register(
17+
normalizeURL(__webpack_public_path__) + 'sw-debug.js'
18+
);
1819
} else if (process.env.ADD_SW && 'serviceWorker' in navigator) {
19-
// eslint-disable-next-line no-undef
2020
navigator.serviceWorker.register(
21-
__webpack_public_path__ + (process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
21+
normalizeURL(__webpack_public_path__) +
22+
(process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
2223
);
2324
}
2425
} else if (process.env.ADD_SW && 'serviceWorker' in navigator) {
25-
// eslint-disable-next-line no-undef
2626
navigator.serviceWorker.register(
27-
__webpack_public_path__ + (process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
27+
normalizeURL(__webpack_public_path__) +
28+
(process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
2829
);
2930
}
3031

@@ -57,7 +58,7 @@ if (typeof app === 'function') {
5758
hydrate &&
5859
currentURL === normalizeURL(location.pathname);
5960
const doRender = canHydrate ? hydrate : render;
60-
root = doRender(h(app, { CLI_DATA }), document.body, root);
61+
doRender(h(app, { CLI_DATA }), document.body, root);
6162
};
6263

6364
if (module.hot) module.hot.accept('preact-cli-entrypoint', init);

packages/cli/lib/lib/webpack/render-html-plugin.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const prerender = require('./prerender');
77
const createLoadManifest = require('./create-load-manifest');
88
const { warn } = require('../../util');
99
const { info } = require('../../util');
10-
const { PRERENDER_DATA_FILE_NAME } = require('../constants');
1110

1211
const PREACT_FALLBACK_URL = '/200.html';
1312

@@ -181,7 +180,7 @@ class PrerenderDataExtractPlugin {
181180
// We dont build prerender data for `200.html`. It can re-use the one for homepage.
182181
return;
183182
}
184-
let path = this.location_ + PRERENDER_DATA_FILE_NAME;
183+
let path = this.location_ + 'preact_prerender_data.json';
185184
if (path.startsWith('/')) {
186185
path = path.substr(1);
187186
}

packages/cli/lib/lib/webpack/run-webpack.js

-16
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,6 @@ async function devBuild(env) {
1717

1818
let compiler = webpack(config);
1919
return new Promise((res, rej) => {
20-
compiler.hooks.emit.tapAsync('CliDevPlugin', (compilation, callback) => {
21-
let missingDeps = compilation.missingDependencies;
22-
let nodeModulesPath = resolve(__dirname, '../../../node_modules');
23-
24-
// ...tell webpack to watch node_modules recursively until they appear.
25-
if (
26-
Array.from(missingDeps).some(
27-
file => file.indexOf(nodeModulesPath) !== -1
28-
)
29-
) {
30-
compilation.contextDependencies.push(nodeModulesPath);
31-
}
32-
33-
callback();
34-
});
35-
3620
compiler.hooks.beforeCompile.tap('CliDevPlugin', () => {
3721
if (env['clear']) clear(true);
3822
});

packages/cli/lib/lib/webpack/webpack-base-config.js

+5-15
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,10 @@ const PnpWebpackPlugin = require(`pnp-webpack-plugin`);
1616

1717
function readJson(file) {
1818
try {
19-
return JSON.parse(readFileSync(file));
19+
return JSON.parse(readFileSync(file, 'utf8'));
2020
} catch (e) {}
2121
}
2222

23-
// attempt to resolve a dependency, giving $CWD/node_modules priority:
24-
// function resolveDep(dep, cwd) {
25-
// try {
26-
// return requireRelative.resolve(dep, cwd || process.cwd());
27-
// } catch (e) {}
28-
// try {
29-
// return require.resolve(dep);
30-
// } catch (e) {}
31-
// return dep;
32-
// }
33-
3423
function findAllNodeModules(startDir) {
3524
let dir = path.resolve(startDir);
3625
let dirs = [];
@@ -70,6 +59,9 @@ function getSassConfiguration(...includePaths) {
7059
return config;
7160
}
7261

62+
/**
63+
* @returns {import('webpack').Configuration}
64+
*/
7365
module.exports = function createBaseConfig(env) {
7466
const { cwd, isProd, isWatch, src, source } = env;
7567
const babelConfigFile = env.babelConfig || '.babelrc';
@@ -331,7 +323,7 @@ module.exports = function createBaseConfig(env) {
331323
? '[name].chunk.[contenthash:5].css'
332324
: '[name].chunk.css',
333325
}),
334-
new ProgressBarPlugin({
326+
ProgressBarPlugin({
335327
format:
336328
'\u001b[97m\u001b[44m Build \u001b[49m\u001b[39m [:bar] \u001b[32m\u001b[1m:percent\u001b[22m\u001b[39m (:elapseds) \u001b[2m:msg\u001b[22m',
337329
renderThrottle: 100,
@@ -388,5 +380,3 @@ module.exports = function createBaseConfig(env) {
388380
},
389381
};
390382
};
391-
392-
module.exports.readJson = readJson;

packages/cli/lib/lib/webpack/webpack-client-config.js

+9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ const cleanFilename = name =>
2525
''
2626
);
2727

28+
/**
29+
* @returns {Promise<import('webpack').Configuration>}
30+
*/
2831
async function clientConfig(env) {
2932
const { isProd, source, src, cwd /*, port? */ } = env;
3033
const IS_SOURCE_PREACT_X_OR_ABOVE = isInstalledVersionPreactXOrAbove(cwd);
@@ -190,6 +193,9 @@ function getBabelEsmPlugin(config) {
190193
return esmPlugins;
191194
}
192195

196+
/**
197+
* @returns {import('webpack').Configuration}
198+
*/
193199
function isProd(config) {
194200
let limit = 200 * 1000; // 200kb
195201
const prodConfig = {
@@ -274,6 +280,9 @@ function isProd(config) {
274280
return prodConfig;
275281
}
276282

283+
/**
284+
* @returns {import('webpack').Configuration}
285+
*/
277286
function isDev(config) {
278287
const { cwd, src, refresh } = config;
279288

packages/cli/lib/lib/webpack/webpack-server-config.js

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ const { resolve } = require('path');
22
const { merge } = require('webpack-merge');
33
const baseConfig = require('./webpack-base-config');
44

5+
/**
6+
* @returns {import('webpack').Configuration}
7+
*/
58
function serverConfig(env) {
69
return {
710
entry: {

packages/cli/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
"bugs": "https://github.com/preactjs/preact-cli/issues",
3434
"homepage": "https://github.com/preactjs/preact-cli",
3535
"devDependencies": {
36+
"@types/express": "^4.17.13",
37+
"@types/jest": "^27.4.0",
3638
"html-looks-like": "^1.0.2",
3739
"jest": "^27.0.1",
3840
"less": "^4.1.1",

packages/cli/tests/build.test.js

+16-32
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ const { existsSync } = require('fs');
33
const { readFile } = require('fs').promises;
44
const looksLike = require('html-looks-like');
55
const { create, build } = require('./lib/cli');
6-
const { snapshot, hasKey, isWithin } = require('./lib/utils');
6+
const { snapshot } = require('./lib/utils');
77
const { subject } = require('./lib/output');
88
const images = require('./images/build');
99
const { promisify } = require('util');
1010
const glob = promisify(require('glob').glob);
11+
const minimatch = require('minimatch');
1112

1213
const prerenderUrlFiles = [
1314
'prerender-urls.json',
@@ -35,13 +36,15 @@ function getRegExpFromMarkup(markup) {
3536
return new RegExp(minifiedMarkup);
3637
}
3738

38-
function testMatch(src, tar) {
39-
let k, tmp;
40-
let keys = Object.keys(tar);
41-
expect(Object.keys(src)).toHaveLength(keys.length);
42-
for (k in src) {
43-
expect(hasKey(k, keys)).toBeTruthy();
44-
if (!isWithin(src[k], tar[tmp])) return false;
39+
function testMatch(received, expected) {
40+
let receivedKeys = Object.keys(received);
41+
let expectedKeys = Object.keys(expected);
42+
expect(receivedKeys).toHaveLength(expectedKeys.length);
43+
for (let key in expected) {
44+
const receivedKey = receivedKeys.find(k => minimatch(k, key));
45+
expect(key).toFindMatchingKey(receivedKey);
46+
47+
expect(receivedKey).toBeCloseInSize(received[receivedKey], expected[key]);
4548
}
4649
}
4750

@@ -184,15 +187,16 @@ describe('preact build', () => {
184187
expect(existsSync(file)).toBe(true);
185188
});
186189

187-
it('should use template from the code folder', async () => {
188-
// app with custom template set via preact.config.js
190+
it('should use custom `template.html`', async () => {
189191
let dir = await subject('custom-template');
190192
await build(dir);
191193

192194
let file = join(dir, 'build/index.html');
193195
let html = await readFile(file, 'utf-8');
194196

195-
looksLike(html, images.template);
197+
expect(html).toEqual(
198+
expect.stringMatching(getRegExpFromMarkup(images.template))
199+
);
196200
});
197201

198202
it('should patch global location object', async () => {
@@ -217,28 +221,8 @@ describe('preact build', () => {
217221
expect(existsSync(file)).toBe(true);
218222
});
219223

220-
it('should inject preact.* variables into template', async () => {
221-
let dir = await subject('custom-template-2');
222-
await build(dir);
223-
224-
let file = join(dir, 'build/index.html');
225-
let html = await readFile(file, 'utf-8');
226-
227-
looksLike(html, images.templateReplaced);
228-
});
229-
230-
it('should replace title with <%= preact.title %>', async () => {
231-
let dir = await subject('custom-template-3');
232-
await build(dir);
233-
234-
let file = join(dir, 'build/index.html');
235-
let html = await readFile(file, 'utf-8');
236-
237-
looksLike(html, images.templateReplaced);
238-
});
239-
240224
it('should error out for invalid argument', async () => {
241-
let dir = await subject('custom-template-3');
225+
let dir = await subject('custom-template');
242226
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
243227
expect(build(dir, { 'service-worker': false })).rejects.toEqual(
244228
new Error('Invalid argument found.')

0 commit comments

Comments
 (0)