Skip to content

Commit

Permalink
Chore: Backport recent refactorings (#1648)
Browse files Browse the repository at this point in the history
  • Loading branch information
rschristian committed Feb 2, 2022
1 parent e98994a commit aa055f6
Show file tree
Hide file tree
Showing 32 changed files with 605 additions and 1,101 deletions.
6 changes: 6 additions & 0 deletions .changeset/rude-walls-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'preact-cli': minor
'@preact/prerender-data-provider': patch
---

Updates to use html-webpack-plugin v4
5 changes: 5 additions & 0 deletions .changeset/silver-taxis-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'preact-cli': patch
---

Ensures the public path is normalized when registering service workers
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
**/node_modules
**/tests/output
**/*.d.ts
10 changes: 1 addition & 9 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,5 @@
"react/jsx-no-undef": 2,
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2
},
"overrides": [
{
"files": ["**/*.ts"],
"rules": {
"no-undef": "off"
}
}
]
}
}
15 changes: 15 additions & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"moduleResolution": "Node",
"allowJs": true,
"checkJs": true,
"noEmit": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"jsx": "react",
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment"
},
"include": ["packages/**/*"]
}
11 changes: 11 additions & 0 deletions packages/cli/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
declare global {
const __webpack_public_path__: string;
namespace jest {
interface Matchers<R> {
toBeCloseInSize(receivedSize: number, expectedSize: number): R;
toFindMatchingKey(receivedKey: string): R;
}
}
}

export {};
4 changes: 2 additions & 2 deletions packages/cli/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const envinfo = require('envinfo');
const sade = require('sade');
const notifier = require('update-notifier');
const { error } = require('./util');
const pkg = require('../package');
const pkg = require('../package.json');

const ver = process.version;
const min = pkg.engines.node;
Expand All @@ -12,7 +12,7 @@ if (
.substring(1)
.localeCompare(min.match(/\d+/g).join('.'), 'en', { numeric: true }) === -1
) {
return error(
error(
`You are using Node ${ver} but preact-cli requires Node ${min}. Please upgrade Node to continue!`,
1
);
Expand Down
5 changes: 0 additions & 5 deletions packages/cli/lib/lib/constants.js

This file was deleted.

15 changes: 8 additions & 7 deletions packages/cli/lib/lib/entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,19 @@ if (process.env.NODE_ENV === 'development') {

// only add a debug sw if webpack service worker is not requested.
if (process.env.ADD_SW === undefined && 'serviceWorker' in navigator) {
// eslint-disable-next-line no-undef
navigator.serviceWorker.register(__webpack_public_path__ + 'sw-debug.js');
navigator.serviceWorker.register(
normalizeURL(__webpack_public_path__) + 'sw-debug.js'
);
} else if (process.env.ADD_SW && 'serviceWorker' in navigator) {
// eslint-disable-next-line no-undef
navigator.serviceWorker.register(
__webpack_public_path__ + (process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
normalizeURL(__webpack_public_path__) +
(process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
);
}
} else if (process.env.ADD_SW && 'serviceWorker' in navigator) {
// eslint-disable-next-line no-undef
navigator.serviceWorker.register(
__webpack_public_path__ + (process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
normalizeURL(__webpack_public_path__) +
(process.env.ES_BUILD ? 'sw-esm.js' : 'sw.js')
);
}

Expand Down Expand Up @@ -57,7 +58,7 @@ if (typeof app === 'function') {
hydrate &&
currentURL === normalizeURL(location.pathname);
const doRender = canHydrate ? hydrate : render;
root = doRender(h(app, { CLI_DATA }), document.body, root);
doRender(h(app, { CLI_DATA }), document.body, root);
};

if (module.hot) module.hot.accept('preact-cli-entrypoint', init);
Expand Down
114 changes: 64 additions & 50 deletions packages/cli/lib/lib/webpack/render-html-plugin.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
const { resolve, join } = require('path');
const os = require('os');
const { existsSync, readFileSync, writeFileSync, mkdirSync } = require('fs');
const HtmlWebpackExcludeAssetsPlugin = require('html-webpack-exclude-assets-plugin');
const {
HtmlWebpackSkipAssetsPlugin,
} = require('html-webpack-skip-assets-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const prerender = require('./prerender');
const createLoadManifest = require('./create-load-manifest');
const { warn } = require('../../util');
const { info } = require('../../util');
const { PRERENDER_DATA_FILE_NAME } = require('../constants');

const PREACT_FALLBACK_URL = '/200.html';

Expand All @@ -17,8 +18,8 @@ function read(path) {
return readFileSync(resolve(__dirname, path), 'utf-8');
}

module.exports = async function (config) {
const { cwd, dest, isProd, src } = config;
module.exports = async function renderHTMLPlugin(config) {
const { cwd, dest, src } = config;
const inProjectTemplatePath = resolve(src, 'template.html');
let template = defaultTemplate;
if (existsSync(inProjectTemplatePath)) {
Expand All @@ -34,14 +35,11 @@ module.exports = async function (config) {
}

let content = read(template);
if (/preact\.headEnd|preact\.bodyEnd/.test(content)) {
if (/preact\.(title|headEnd|bodyEnd)/.test(content)) {
const headEnd = read('../../resources/head-end.ejs');
const bodyEnd = read('../../resources/body-end.ejs');
content = content
.replace(
/<%[=]?\s+preact\.title\s+%>/,
'<%= htmlWebpackPlugin.options.title %>'
)
.replace(/<%[=]?\s+preact\.title\s+%>/, '<%= cli.title %>')
.replace(/<%\s+preact\.headEnd\s+%>/, headEnd)
.replace(/<%\s+preact\.bodyEnd\s+%>/, bodyEnd);

Expand All @@ -56,53 +54,70 @@ module.exports = async function (config) {
}

const htmlWebpackConfig = values => {
const { url, title, ...routeData } = values;
let { url, title, ...routeData } = values;

title =
title ||
config.title ||
config.manifest.name ||
config.manifest.short_name ||
(config.pkg.name || '').replace(/^@[a-z]\//, '') ||
'Preact App';

// Do not create a folder if the url is for a specific file.
const filename = url.endsWith('.html')
? resolve(dest, url.substring(1))
: resolve(dest, url.substring(1), 'index.html');
return Object.assign(values, {

return {
title,
filename,
template: `!!${require.resolve('ejs-loader')}?esModule=false!${template}`,
minify: isProd && {
collapseWhitespace: true,
removeScriptTypeAttributes: true,
removeRedundantAttributes: true,
removeStyleLinkTypeAttributes: true,
removeComments: true,
templateParameters: (compilation, assets, assetTags, options) => {
let entrypoints = {};
compilation.entrypoints.forEach((entrypoint, name) => {
let entryFiles = entrypoint.getFiles();
entrypoints[name] =
assets.publicPath +
entryFiles.find(file => /\.(m?js)(\?|$)/.test(file));
});

let loadManifest = compilation.assets['push-manifest.json']
? JSON.parse(compilation.assets['push-manifest.json'].source())
: createLoadManifest(
compilation.assets,
config.esm,
compilation.namedChunkGroups
);

return {
cli: {
title,
url,
manifest: config.manifest,
inlineCss: config['inline-css'],
preload: config.preload,
config,
preRenderData: values,
CLI_DATA: { preRenderData: { url, ...routeData } },
ssr: config.prerender ? prerender({ cwd, dest, src }, values) : '',
loadManifest,
entrypoints,
},
htmlWebpackPlugin: {
tags: assetTags,
files: assets,
options,
},
};
},
inject: true,
scriptLoading: 'defer',
favicon: existsSync(resolve(src, 'assets/favicon.ico'))
? 'assets/favicon.ico'
: '',
inject: true,
compile: true,
inlineCss: config['inline-css'],
preload: config.preload,
manifest: config.manifest,
title:
title ||
config.title ||
config.manifest.name ||
config.manifest.short_name ||
(config.pkg.name || '').replace(/^@[a-z]\//, '') ||
'Preact App',
excludeAssets: [/(bundle|polyfills)(\..*)?\.js$/],
createLoadManifest: (assets, namedChunkGroups) => {
if (assets['push-manifest.json']) {
return JSON.parse(assets['push-manifest.json'].source());
}
return createLoadManifest(assets, config.esm, namedChunkGroups);
},
config,
url,
ssr() {
return config.prerender && url !== PREACT_FALLBACK_URL
? prerender({ cwd, dest, src }, values)
: '';
},
scriptLoading: 'defer',
CLI_DATA: { preRenderData: { url, ...routeData } },
});
};
};

let pages = [{ url: '/' }];
Expand Down Expand Up @@ -158,7 +173,7 @@ module.exports = async function (config) {
const resultPages = pages
.map(htmlWebpackConfig)
.map(conf => new HtmlWebpackPlugin(conf))
.concat([new HtmlWebpackExcludeAssetsPlugin()]);
.concat([new HtmlWebpackSkipAssetsPlugin()]);

return config.prerender
? resultPages.concat([
Expand All @@ -170,18 +185,17 @@ module.exports = async function (config) {
// Adds a preact_prerender_data in every folder so that the data could be fetched separately.
class PrerenderDataExtractPlugin {
constructor(page) {
const cliData = page.CLI_DATA || {};
const { url } = cliData.preRenderData || {};
const url = page.url;
this.location_ = url.endsWith('/') ? url : url + '/';
this.data_ = JSON.stringify(cliData.preRenderData || {});
this.data_ = JSON.stringify(page || {});
}
apply(compiler) {
compiler.hooks.emit.tap('PrerenderDataExtractPlugin', compilation => {
if (this.location_ === `${PREACT_FALLBACK_URL}/`) {
// We dont build prerender data for `200.html`. It can re-use the one for homepage.
return;
}
let path = this.location_ + PRERENDER_DATA_FILE_NAME;
let path = this.location_ + 'preact_prerender_data.json';
if (path.startsWith('/')) {
path = path.substr(1);
}
Expand Down
16 changes: 0 additions & 16 deletions packages/cli/lib/lib/webpack/run-webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,6 @@ async function devBuild(env) {

let compiler = webpack(config);
return new Promise((res, rej) => {
compiler.hooks.emit.tapAsync('CliDevPlugin', (compilation, callback) => {
let missingDeps = compilation.missingDependencies;
let nodeModulesPath = resolve(__dirname, '../../../node_modules');

// ...tell webpack to watch node_modules recursively until they appear.
if (
Array.from(missingDeps).some(
file => file.indexOf(nodeModulesPath) !== -1
)
) {
compilation.contextDependencies.push(nodeModulesPath);
}

callback();
});

compiler.hooks.beforeCompile.tap('CliDevPlugin', () => {
if (env['clear']) clear(true);
});
Expand Down
20 changes: 5 additions & 15 deletions packages/cli/lib/lib/webpack/webpack-base-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,10 @@ const PnpWebpackPlugin = require(`pnp-webpack-plugin`);

function readJson(file) {
try {
return JSON.parse(readFileSync(file));
return JSON.parse(readFileSync(file, 'utf8'));
} catch (e) {}
}

// attempt to resolve a dependency, giving $CWD/node_modules priority:
// function resolveDep(dep, cwd) {
// try {
// return requireRelative.resolve(dep, cwd || process.cwd());
// } catch (e) {}
// try {
// return require.resolve(dep);
// } catch (e) {}
// return dep;
// }

function findAllNodeModules(startDir) {
let dir = path.resolve(startDir);
let dirs = [];
Expand Down Expand Up @@ -70,6 +59,9 @@ function getSassConfiguration(...includePaths) {
return config;
}

/**
* @returns {import('webpack').Configuration}
*/
module.exports = function createBaseConfig(env) {
const { cwd, isProd, isWatch, src, source } = env;
const babelConfigFile = env.babelConfig || '.babelrc';
Expand Down Expand Up @@ -331,7 +323,7 @@ module.exports = function createBaseConfig(env) {
? '[name].chunk.[contenthash:5].css'
: '[name].chunk.css',
}),
new ProgressBarPlugin({
ProgressBarPlugin({
format:
'\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',
renderThrottle: 100,
Expand Down Expand Up @@ -388,5 +380,3 @@ module.exports = function createBaseConfig(env) {
},
};
};

module.exports.readJson = readJson;

0 comments on commit aa055f6

Please sign in to comment.