feat: cleanup webpack deps (#14530)
#### PR Dependency Tree * **PR #14530** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Breaking Changes** * Webpack bundler support removed from the build system * Bundler selection parameter removed from build and development commands * **Refactor** * Build configuration consolidated to a single bundler approach * Webpack-specific build paths and workflows removed; development server simplified * **Chores** * Removed webpack-related dev dependencies and tooling * Updated package build scripts for a unified bundle command * **Dependencies** * Upgraded Sentry packages across frontend packages (react/electron/esbuild plugin) <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
292
tools/cli/src/rspack-shared/html-plugin.ts
Normal file
292
tools/cli/src/rspack-shared/html-plugin.ts
Normal file
@@ -0,0 +1,292 @@
|
||||
import { execSync } from 'node:child_process';
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
import { Path, ProjectRoot } from '@affine-tools/utils/path';
|
||||
import { Repository } from '@napi-rs/simple-git';
|
||||
import HTMLPlugin from 'html-webpack-plugin';
|
||||
import { once } from 'lodash-es';
|
||||
|
||||
type PluginLike = {
|
||||
apply: (compiler: CompilerLike) => void;
|
||||
};
|
||||
|
||||
type CompilerLike = {
|
||||
webpack?: {
|
||||
sources?: {
|
||||
RawSource?: new (source: string) => unknown;
|
||||
};
|
||||
};
|
||||
hooks: {
|
||||
compilation: {
|
||||
tap: (name: string, callback: (compilation: any) => void) => void;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
function createRawSource(compiler: CompilerLike, source: string) {
|
||||
const RawSource = compiler.webpack?.sources?.RawSource;
|
||||
if (!RawSource) {
|
||||
throw new Error(
|
||||
'compiler.webpack.sources.RawSource is required for html plugin assets emission'
|
||||
);
|
||||
}
|
||||
|
||||
return new RawSource(source);
|
||||
}
|
||||
|
||||
export const getPublicPath = (BUILD_CONFIG: BUILD_CONFIG_TYPE) => {
|
||||
const { BUILD_TYPE } = process.env;
|
||||
if (typeof process.env.PUBLIC_PATH === 'string') {
|
||||
return process.env.PUBLIC_PATH;
|
||||
}
|
||||
|
||||
if (
|
||||
BUILD_CONFIG.debug ||
|
||||
BUILD_CONFIG.distribution === 'desktop' ||
|
||||
BUILD_CONFIG.distribution === 'ios' ||
|
||||
BUILD_CONFIG.distribution === 'android'
|
||||
) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
switch (BUILD_TYPE) {
|
||||
case 'stable':
|
||||
return 'https://prod.affineassets.com/';
|
||||
case 'beta':
|
||||
return 'https://beta.affineassets.com/';
|
||||
default:
|
||||
return 'https://dev.affineassets.com/';
|
||||
}
|
||||
};
|
||||
|
||||
const DESCRIPTION = `There can be more than Notion and Miro. AFFiNE is a next-gen knowledge base that brings planning, sorting and creating all together.`;
|
||||
|
||||
const gitShortHash = once(() => {
|
||||
const { GITHUB_SHA } = process.env;
|
||||
if (GITHUB_SHA) {
|
||||
return GITHUB_SHA.substring(0, 9);
|
||||
}
|
||||
const repo = new Repository(ProjectRoot.value);
|
||||
const shortSha = repo.head().target()?.substring(0, 9);
|
||||
if (shortSha) {
|
||||
return shortSha;
|
||||
}
|
||||
const sha = execSync(`git rev-parse --short HEAD`, {
|
||||
encoding: 'utf-8',
|
||||
}).trim();
|
||||
return sha;
|
||||
});
|
||||
|
||||
const currentDir = Path.dir(import.meta.url);
|
||||
|
||||
export interface CreateHTMLPluginConfig {
|
||||
filename?: string;
|
||||
additionalEntryForSelfhost?: boolean;
|
||||
selfhostPublicPath?: string;
|
||||
injectGlobalErrorHandler?: boolean;
|
||||
emitAssetsManifest?: boolean;
|
||||
}
|
||||
|
||||
function getHTMLPluginOptions(BUILD_CONFIG: BUILD_CONFIG_TYPE) {
|
||||
const publicPath = getPublicPath(BUILD_CONFIG);
|
||||
const cdnOrigin = publicPath.startsWith('/')
|
||||
? undefined
|
||||
: new URL(publicPath).origin;
|
||||
|
||||
const templateParams = {
|
||||
GIT_SHORT_SHA: gitShortHash(),
|
||||
DESCRIPTION,
|
||||
PRECONNECT: cdnOrigin
|
||||
? `<link rel="preconnect" href="${cdnOrigin}" />`
|
||||
: '',
|
||||
VIEWPORT_FIT: BUILD_CONFIG.isMobileEdition ? 'cover' : 'auto',
|
||||
};
|
||||
|
||||
return {
|
||||
template: currentDir.join('template.html').toString(),
|
||||
inject: 'body',
|
||||
minify: false,
|
||||
templateParameters: templateParams,
|
||||
chunks: ['app'],
|
||||
scriptLoading: 'blocking',
|
||||
} satisfies HTMLPlugin.Options;
|
||||
}
|
||||
|
||||
const AssetsManifestPlugin = {
|
||||
apply(compiler: CompilerLike) {
|
||||
compiler.hooks.compilation.tap('assets-manifest-plugin', compilation => {
|
||||
HTMLPlugin.getHooks(compilation).beforeAssetTagGeneration.tap(
|
||||
'assets-manifest-plugin',
|
||||
arg => {
|
||||
if (!compilation.getAsset('assets-manifest.json')) {
|
||||
compilation.emitAsset(
|
||||
`assets-manifest.json`,
|
||||
createRawSource(
|
||||
compiler,
|
||||
JSON.stringify(
|
||||
{
|
||||
...arg.assets,
|
||||
js: arg.assets.js.map(file =>
|
||||
file.substring(arg.assets.publicPath.length)
|
||||
),
|
||||
css: arg.assets.css.map(file =>
|
||||
file.substring(arg.assets.publicPath.length)
|
||||
),
|
||||
gitHash: gitShortHash(),
|
||||
description: DESCRIPTION,
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
),
|
||||
{
|
||||
immutable: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const GlobalErrorHandlerPlugin = {
|
||||
apply(compiler: CompilerLike) {
|
||||
const globalErrorHandler = [
|
||||
'js/global-error-handler.js',
|
||||
readFileSync(currentDir.join('./error-handler.js').toString(), 'utf-8'),
|
||||
];
|
||||
|
||||
compiler.hooks.compilation.tap(
|
||||
'global-error-handler-plugin',
|
||||
compilation => {
|
||||
HTMLPlugin.getHooks(compilation).beforeAssetTagGeneration.tap(
|
||||
'global-error-handler-plugin',
|
||||
arg => {
|
||||
if (!compilation.getAsset(globalErrorHandler[0])) {
|
||||
compilation.emitAsset(
|
||||
globalErrorHandler[0],
|
||||
createRawSource(compiler, globalErrorHandler[1])
|
||||
);
|
||||
arg.assets.js.unshift(
|
||||
arg.assets.publicPath + globalErrorHandler[0]
|
||||
);
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const CorsPlugin = {
|
||||
apply(compiler: CompilerLike) {
|
||||
compiler.hooks.compilation.tap('html-js-cors-plugin', compilation => {
|
||||
HTMLPlugin.getHooks(compilation).alterAssetTags.tap(
|
||||
'html-js-cors-plugin',
|
||||
options => {
|
||||
if (options.publicPath !== '/') {
|
||||
options.assetTags.scripts.forEach(script => {
|
||||
script.attributes.crossorigin = true;
|
||||
});
|
||||
options.assetTags.styles.forEach(style => {
|
||||
style.attributes.crossorigin = true;
|
||||
});
|
||||
}
|
||||
return options;
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export function createHTMLPlugins(
|
||||
BUILD_CONFIG: BUILD_CONFIG_TYPE,
|
||||
config: CreateHTMLPluginConfig
|
||||
): (HTMLPlugin | PluginLike)[] {
|
||||
const publicPath = getPublicPath(BUILD_CONFIG);
|
||||
const htmlPluginOptions = getHTMLPluginOptions(BUILD_CONFIG);
|
||||
const selfhostPublicPath = config.selfhostPublicPath ?? '/';
|
||||
|
||||
const plugins: (HTMLPlugin | PluginLike)[] = [];
|
||||
plugins.push(
|
||||
new HTMLPlugin({
|
||||
...htmlPluginOptions,
|
||||
chunks: ['index'],
|
||||
filename: config.filename,
|
||||
publicPath,
|
||||
meta: {
|
||||
'env:publicPath': publicPath,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
if (BUILD_CONFIG.isElectron) {
|
||||
plugins.push(
|
||||
new HTMLPlugin({
|
||||
...htmlPluginOptions,
|
||||
chunks: ['shell'],
|
||||
filename: 'shell.html',
|
||||
publicPath,
|
||||
meta: {
|
||||
'env:publicPath': publicPath,
|
||||
},
|
||||
}),
|
||||
new HTMLPlugin({
|
||||
...htmlPluginOptions,
|
||||
filename: 'popup.html',
|
||||
chunks: ['popup'],
|
||||
publicPath,
|
||||
meta: {
|
||||
'env:publicPath': publicPath,
|
||||
},
|
||||
}),
|
||||
new HTMLPlugin({
|
||||
...htmlPluginOptions,
|
||||
filename: 'background-worker.html',
|
||||
chunks: ['backgroundWorker'],
|
||||
publicPath,
|
||||
meta: {
|
||||
'env:publicPath': publicPath,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (!BUILD_CONFIG.isElectron) {
|
||||
plugins.push(CorsPlugin);
|
||||
}
|
||||
|
||||
if (config.emitAssetsManifest) {
|
||||
plugins.push(AssetsManifestPlugin);
|
||||
}
|
||||
|
||||
if (config.injectGlobalErrorHandler) {
|
||||
plugins.push(GlobalErrorHandlerPlugin);
|
||||
}
|
||||
|
||||
if (config.additionalEntryForSelfhost) {
|
||||
plugins.push(
|
||||
new HTMLPlugin({
|
||||
...htmlPluginOptions,
|
||||
chunks: ['index'],
|
||||
publicPath: selfhostPublicPath,
|
||||
meta: {
|
||||
'env:isSelfHosted': 'true',
|
||||
'env:publicPath': selfhostPublicPath,
|
||||
},
|
||||
filename: 'selfhost.html',
|
||||
templateParameters: {
|
||||
...htmlPluginOptions.templateParameters,
|
||||
PRECONNECT: '',
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return plugins;
|
||||
}
|
||||
Reference in New Issue
Block a user