mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-03-22 23:30:36 +08:00
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:
46
.github/workflows/build-test.yml
vendored
46
.github/workflows/build-test.yml
vendored
@@ -282,52 +282,6 @@ jobs:
|
|||||||
path: ./test-results
|
path: ./test-results
|
||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
|
|
||||||
bundler-matrix:
|
|
||||||
name: Bundler Matrix (${{ matrix.bundler }})
|
|
||||||
runs-on: ubuntu-24.04-arm
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
bundler: [webpack, rspack]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
with:
|
|
||||||
playwright-install: false
|
|
||||||
electron-install: false
|
|
||||||
full-cache: true
|
|
||||||
|
|
||||||
- name: Run frontend build matrix
|
|
||||||
env:
|
|
||||||
AFFINE_BUNDLER: ${{ matrix.bundler }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
packages=(
|
|
||||||
"@affine/web"
|
|
||||||
"@affine/mobile"
|
|
||||||
"@affine/ios"
|
|
||||||
"@affine/android"
|
|
||||||
"@affine/admin"
|
|
||||||
"@affine/electron-renderer"
|
|
||||||
)
|
|
||||||
summary="test-results-bundler-${AFFINE_BUNDLER}.txt"
|
|
||||||
: > "$summary"
|
|
||||||
for pkg in "${packages[@]}"; do
|
|
||||||
start=$(date +%s)
|
|
||||||
yarn affine "$pkg" build
|
|
||||||
end=$(date +%s)
|
|
||||||
echo "${pkg},$((end-start))" >> "$summary"
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Upload bundler timing
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: test-results-bundler-${{ matrix.bundler }}
|
|
||||||
path: ./test-results-bundler-${{ matrix.bundler }}.txt
|
|
||||||
if-no-files-found: ignore
|
|
||||||
|
|
||||||
e2e-test:
|
e2e-test:
|
||||||
name: E2E Test
|
name: E2E Test
|
||||||
runs-on: ubuntu-24.04-arm
|
runs-on: ubuntu-24.04-arm
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
import fs from 'node:fs/promises';
|
|
||||||
import path from 'node:path';
|
|
||||||
|
|
||||||
import { build } from 'esbuild';
|
|
||||||
|
|
||||||
const result = await build({
|
|
||||||
entryPoints: ['./src/index.ts'],
|
|
||||||
bundle: true,
|
|
||||||
platform: 'node',
|
|
||||||
outdir: 'dist',
|
|
||||||
target: 'es2024',
|
|
||||||
sourcemap: true,
|
|
||||||
format: 'esm',
|
|
||||||
external: ['yjs'],
|
|
||||||
metafile: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (process.env.METAFILE) {
|
|
||||||
await fs.writeFile(
|
|
||||||
path.resolve(`metafile-${Date.now()}.json`),
|
|
||||||
JSON.stringify(result.metafile, null, 2)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
"./dist": "./dist/index.js"
|
"./dist": "./dist/index.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn bundle",
|
"build": "affine bundle -p @affine/reader",
|
||||||
"bundle": "node esbuild.config.js"
|
"bundle": "affine bundle -p @affine/reader"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lodash-es": "^4.17.23",
|
"lodash-es": "^4.17.23",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
"@radix-ui/react-toggle": "^1.1.1",
|
"@radix-ui/react-toggle": "^1.1.1",
|
||||||
"@radix-ui/react-toggle-group": "^1.1.1",
|
"@radix-ui/react-toggle-group": "^1.1.1",
|
||||||
"@radix-ui/react-tooltip": "^1.1.5",
|
"@radix-ui/react-tooltip": "^1.1.5",
|
||||||
"@sentry/react": "^9.47.1",
|
"@sentry/react": "^10.40.0",
|
||||||
"@tanstack/react-table": "^8.20.5",
|
"@tanstack/react-table": "^8.20.5",
|
||||||
"@toeverything/infra": "workspace:*",
|
"@toeverything/infra": "workspace:*",
|
||||||
"@toeverything/theme": "^1.1.23",
|
"@toeverything/theme": "^1.1.23",
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
"@capacitor/keyboard": "^7.0.0",
|
"@capacitor/keyboard": "^7.0.0",
|
||||||
"@capacitor/status-bar": "^7.0.0",
|
"@capacitor/status-bar": "^7.0.0",
|
||||||
"@capgo/inappbrowser": "^8.0.0",
|
"@capgo/inappbrowser": "^8.0.0",
|
||||||
"@sentry/react": "^9.47.1",
|
"@sentry/react": "^10.40.0",
|
||||||
"@toeverything/infra": "workspace:*",
|
"@toeverything/infra": "workspace:*",
|
||||||
"async-call-rpc": "^6.4.2",
|
"async-call-rpc": "^6.4.2",
|
||||||
"idb": "^8.0.0",
|
"idb": "^8.0.0",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"@affine/track": "workspace:*",
|
"@affine/track": "workspace:*",
|
||||||
"@blocksuite/affine": "workspace:*",
|
"@blocksuite/affine": "workspace:*",
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@sentry/react": "^9.47.1",
|
"@sentry/react": "^10.40.0",
|
||||||
"@toeverything/infra": "workspace:*",
|
"@toeverything/infra": "workspace:*",
|
||||||
"@toeverything/theme": "^1.1.23",
|
"@toeverything/theme": "^1.1.23",
|
||||||
"@vanilla-extract/css": "^1.17.0",
|
"@vanilla-extract/css": "^1.17.0",
|
||||||
|
|||||||
@@ -38,7 +38,6 @@
|
|||||||
"@affine/nbstore": "workspace:*",
|
"@affine/nbstore": "workspace:*",
|
||||||
"@electron-forge/cli": "^7.10.2",
|
"@electron-forge/cli": "^7.10.2",
|
||||||
"@electron-forge/core": "^7.10.2",
|
"@electron-forge/core": "^7.10.2",
|
||||||
"@electron-forge/core-utils": "^7.10.2",
|
|
||||||
"@electron-forge/maker-deb": "^7.10.2",
|
"@electron-forge/maker-deb": "^7.10.2",
|
||||||
"@electron-forge/maker-dmg": "^7.10.2",
|
"@electron-forge/maker-dmg": "^7.10.2",
|
||||||
"@electron-forge/maker-flatpak": "^7.10.2",
|
"@electron-forge/maker-flatpak": "^7.10.2",
|
||||||
@@ -48,9 +47,9 @@
|
|||||||
"@electron-forge/plugin-fuses": "^7.10.2",
|
"@electron-forge/plugin-fuses": "^7.10.2",
|
||||||
"@electron-forge/shared-types": "^7.10.2",
|
"@electron-forge/shared-types": "^7.10.2",
|
||||||
"@reforged/maker-appimage": "^5.2.0",
|
"@reforged/maker-appimage": "^5.2.0",
|
||||||
"@sentry/electron": "^7.0.0",
|
"@sentry/electron": "^7.9.0",
|
||||||
"@sentry/esbuild-plugin": "^4.0.0",
|
"@sentry/esbuild-plugin": "^5.1.1",
|
||||||
"@sentry/react": "^9.47.1",
|
"@sentry/react": "^10.40.0",
|
||||||
"@toeverything/infra": "workspace:*",
|
"@toeverything/infra": "workspace:*",
|
||||||
"@types/set-cookie-parser": "^2.4.10",
|
"@types/set-cookie-parser": "^2.4.10",
|
||||||
"@types/uuid": "^11.0.0",
|
"@types/uuid": "^11.0.0",
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
"@capacitor/haptics": "^7.0.0",
|
"@capacitor/haptics": "^7.0.0",
|
||||||
"@capacitor/ios": "^7.0.0",
|
"@capacitor/ios": "^7.0.0",
|
||||||
"@capacitor/keyboard": "^7.0.0",
|
"@capacitor/keyboard": "^7.0.0",
|
||||||
"@sentry/react": "^9.47.1",
|
"@sentry/react": "^10.40.0",
|
||||||
"@toeverything/infra": "workspace:^",
|
"@toeverything/infra": "workspace:^",
|
||||||
"async-call-rpc": "^6.4.2",
|
"async-call-rpc": "^6.4.2",
|
||||||
"capacitor-plugin-app-tracking-transparency": "^2.0.5",
|
"capacitor-plugin-app-tracking-transparency": "^2.0.5",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"@affine/track": "workspace:*",
|
"@affine/track": "workspace:*",
|
||||||
"@blocksuite/affine": "workspace:*",
|
"@blocksuite/affine": "workspace:*",
|
||||||
"@blocksuite/icons": "^2.2.17",
|
"@blocksuite/icons": "^2.2.17",
|
||||||
"@sentry/react": "^9.47.1",
|
"@sentry/react": "^10.40.0",
|
||||||
"@toeverything/infra": "workspace:*",
|
"@toeverything/infra": "workspace:*",
|
||||||
"react": "^19.2.1",
|
"react": "^19.2.1",
|
||||||
"react-dom": "^19.2.1",
|
"react-dom": "^19.2.1",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
"@affine/nbstore": "workspace:*",
|
"@affine/nbstore": "workspace:*",
|
||||||
"@affine/track": "workspace:*",
|
"@affine/track": "workspace:*",
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@sentry/react": "^9.47.1",
|
"@sentry/react": "^10.40.0",
|
||||||
"@toeverything/infra": "workspace:*",
|
"@toeverything/infra": "workspace:*",
|
||||||
"react": "^19.2.1",
|
"react": "^19.2.1",
|
||||||
"react-dom": "^19.2.1",
|
"react-dom": "^19.2.1",
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
"@radix-ui/react-scroll-area": "^1.2.2",
|
"@radix-ui/react-scroll-area": "^1.2.2",
|
||||||
"@radix-ui/react-slot": "^1.1.1",
|
"@radix-ui/react-slot": "^1.1.1",
|
||||||
"@radix-ui/react-toolbar": "^1.1.1",
|
"@radix-ui/react-toolbar": "^1.1.1",
|
||||||
"@sentry/react": "^9.47.1",
|
"@sentry/react": "^10.40.0",
|
||||||
"@toeverything/infra": "workspace:*",
|
"@toeverything/infra": "workspace:*",
|
||||||
"@toeverything/pdf-viewer": "^0.1.1",
|
"@toeverything/pdf-viewer": "^0.1.1",
|
||||||
"@toeverything/theme": "^1.1.23",
|
"@toeverything/theme": "^1.1.23",
|
||||||
|
|||||||
1
packages/frontend/core/src/types/types.d.ts
vendored
1
packages/frontend/core/src/types/types.d.ts
vendored
@@ -1,4 +1,3 @@
|
|||||||
/// <reference types="@webpack/env" />
|
|
||||||
/// <reference types="@rspack/core/module" />
|
/// <reference types="@rspack/core/module" />
|
||||||
|
|
||||||
declare module '*.md' {
|
declare module '*.md' {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@affine/debug": "workspace:*",
|
"@affine/debug": "workspace:*",
|
||||||
"@sentry/react": "^9.47.1",
|
"@sentry/react": "^10.40.0",
|
||||||
"nanoid": "^5.1.6",
|
"nanoid": "^5.1.6",
|
||||||
"react-router-dom": "^6.30.3"
|
"react-router-dom": "^6.30.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
"@affine-test/kit": "workspace:*",
|
"@affine-test/kit": "workspace:*",
|
||||||
"@affine-tools/cli": "workspace:*",
|
"@affine-tools/cli": "workspace:*",
|
||||||
"@affine-tools/utils": "workspace:*",
|
"@affine-tools/utils": "workspace:*",
|
||||||
"@playwright/test": "=1.58.2",
|
"@playwright/test": "=1.58.2"
|
||||||
"webpack": "^5.102.1"
|
|
||||||
},
|
},
|
||||||
"version": "0.26.3"
|
"version": "0.26.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,14 @@
|
|||||||
"@affine-tools/utils": "workspace:*",
|
"@affine-tools/utils": "workspace:*",
|
||||||
"@affine/s3-compat": "workspace:*",
|
"@affine/s3-compat": "workspace:*",
|
||||||
"@napi-rs/simple-git": "^0.1.22",
|
"@napi-rs/simple-git": "^0.1.22",
|
||||||
"@perfsee/webpack": "^1.13.0",
|
|
||||||
"@rspack/core": "^1.7.6",
|
"@rspack/core": "^1.7.6",
|
||||||
"@rspack/dev-server": "^1.1.3",
|
"@rspack/dev-server": "^1.1.3",
|
||||||
"@sentry/webpack-plugin": "^4.0.0",
|
"@sentry/webpack-plugin": "^5.1.1",
|
||||||
"@swc/core": "^1.10.1",
|
"@swc/core": "^1.10.1",
|
||||||
"@tailwindcss/postcss": "^4.0.0",
|
"@tailwindcss/postcss": "^4.0.0",
|
||||||
"@vanilla-extract/webpack-plugin": "^2.3.15",
|
"@vanilla-extract/webpack-plugin": "^2.3.15",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"clipanion": "^3.2.1",
|
"clipanion": "^3.2.1",
|
||||||
"copy-webpack-plugin": "^13.0.0",
|
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"cssnano": "^7.0.6",
|
"cssnano": "^7.0.6",
|
||||||
"html-webpack-plugin": "^5.6.3",
|
"html-webpack-plugin": "^5.6.3",
|
||||||
@@ -35,7 +33,6 @@
|
|||||||
"jsonc-parser": "^3.3.1",
|
"jsonc-parser": "^3.3.1",
|
||||||
"lodash-es": "^4.17.23",
|
"lodash-es": "^4.17.23",
|
||||||
"mime-types": "^3.0.0",
|
"mime-types": "^3.0.0",
|
||||||
"mini-css-extract-plugin": "^2.9.2",
|
|
||||||
"node-loader": "^2.1.0",
|
"node-loader": "^2.1.0",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.4.49",
|
||||||
"postcss-loader": "^8.1.1",
|
"postcss-loader": "^8.1.1",
|
||||||
@@ -46,18 +43,13 @@
|
|||||||
"style-loader": "^4.0.0",
|
"style-loader": "^4.0.0",
|
||||||
"swc-loader": "^0.2.6",
|
"swc-loader": "^0.2.6",
|
||||||
"tailwindcss": "^4.1.17",
|
"tailwindcss": "^4.1.17",
|
||||||
"terser-webpack-plugin": "^5.3.10",
|
|
||||||
"tsx": "^4.21.0",
|
"tsx": "^4.21.0",
|
||||||
"typanion": "^3.14.0",
|
"typanion": "^3.14.0",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3"
|
||||||
"webpack": "^5.102.1",
|
|
||||||
"webpack-dev-server": "^5.2.0",
|
|
||||||
"webpack-merge": "^6.0.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/mime-types": "^3.0.0",
|
"@types/mime-types": "^3.0.0",
|
||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0"
|
||||||
"@types/webpack-env": "^1.18.5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
|
import type { Configuration as RspackDevServerConfiguration } from '@rspack/dev-server';
|
||||||
|
|
||||||
export const RSPACK_SUPPORTED_PACKAGES = [
|
export const RSPACK_SUPPORTED_PACKAGES = [
|
||||||
'@affine/admin',
|
'@affine/admin',
|
||||||
@@ -8,6 +8,7 @@ export const RSPACK_SUPPORTED_PACKAGES = [
|
|||||||
'@affine/android',
|
'@affine/android',
|
||||||
'@affine/electron-renderer',
|
'@affine/electron-renderer',
|
||||||
'@affine/server',
|
'@affine/server',
|
||||||
|
'@affine/reader',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
const rspackSupportedPackageSet = new Set<string>(RSPACK_SUPPORTED_PACKAGES);
|
const rspackSupportedPackageSet = new Set<string>(RSPACK_SUPPORTED_PACKAGES);
|
||||||
@@ -22,14 +23,14 @@ export function assertRspackSupportedPackageName(name: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`AFFINE_BUNDLER=rspack currently supports: ${Array.from(RSPACK_SUPPORTED_PACKAGES).join(', ')}. Use AFFINE_BUNDLER=webpack for ${name}.`
|
`Rspack bundling currently supports: ${Array.from(RSPACK_SUPPORTED_PACKAGES).join(', ')}. Unsupported package: ${name}.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const IN_CI = !!process.env.CI;
|
const IN_CI = !!process.env.CI;
|
||||||
const httpProxyMiddlewareLogLevel = IN_CI ? 'silent' : 'error';
|
const httpProxyMiddlewareLogLevel = IN_CI ? 'silent' : 'error';
|
||||||
|
|
||||||
export const DEFAULT_DEV_SERVER_CONFIG: WebpackDevServerConfiguration = {
|
export const DEFAULT_DEV_SERVER_CONFIG: RspackDevServerConfiguration = {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
allowedHosts: 'all',
|
allowedHosts: 'all',
|
||||||
hot: false,
|
hot: false,
|
||||||
|
|||||||
@@ -9,32 +9,21 @@ import {
|
|||||||
RspackDevServer,
|
RspackDevServer,
|
||||||
} from '@rspack/dev-server';
|
} from '@rspack/dev-server';
|
||||||
import { merge } from 'lodash-es';
|
import { merge } from 'lodash-es';
|
||||||
import webpack from 'webpack';
|
|
||||||
import WebpackDevServer, {
|
|
||||||
type Configuration as WebpackDevServerConfiguration,
|
|
||||||
} from 'webpack-dev-server';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
assertRspackSupportedPackageName,
|
assertRspackSupportedPackageName,
|
||||||
DEFAULT_DEV_SERVER_CONFIG,
|
DEFAULT_DEV_SERVER_CONFIG,
|
||||||
isRspackSupportedPackageName,
|
|
||||||
} from './bundle-shared';
|
} from './bundle-shared';
|
||||||
import { type Bundler, getBundler } from './bundler';
|
|
||||||
import { Option, PackageCommand } from './command';
|
import { Option, PackageCommand } from './command';
|
||||||
import {
|
import {
|
||||||
createHTMLTargetConfig as createRspackHTMLTargetConfig,
|
createHTMLTargetConfig as createRspackHTMLTargetConfig,
|
||||||
createNodeTargetConfig as createRspackNodeTargetConfig,
|
createNodeTargetConfig as createRspackNodeTargetConfig,
|
||||||
createWorkerTargetConfig as createRspackWorkerTargetConfig,
|
createWorkerTargetConfig as createRspackWorkerTargetConfig,
|
||||||
} from './rspack';
|
} from './rspack';
|
||||||
import {
|
|
||||||
createHTMLTargetConfig as createWebpackHTMLTargetConfig,
|
|
||||||
createNodeTargetConfig as createWebpackNodeTargetConfig,
|
|
||||||
createWorkerTargetConfig as createWebpackWorkerTargetConfig,
|
|
||||||
} from './webpack';
|
|
||||||
import {
|
import {
|
||||||
shouldUploadReleaseAssets,
|
shouldUploadReleaseAssets,
|
||||||
uploadDistAssetsToS3,
|
uploadDistAssetsToS3,
|
||||||
} from './webpack/s3-plugin.js';
|
} from './rspack-shared/s3-plugin.js';
|
||||||
|
|
||||||
type WorkerConfig = { name: string };
|
type WorkerConfig = { name: string };
|
||||||
type CreateWorkerTargetConfig = (pkg: Package, entry: string) => WorkerConfig;
|
type CreateWorkerTargetConfig = (pkg: Package, entry: string) => WorkerConfig;
|
||||||
@@ -84,78 +73,6 @@ function getBaseWorkerConfigs(
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWebpackBundleConfigs(pkg: Package): webpack.MultiConfiguration {
|
|
||||||
switch (pkg.name) {
|
|
||||||
case '@affine/admin': {
|
|
||||||
return [
|
|
||||||
createWebpackHTMLTargetConfig(
|
|
||||||
pkg,
|
|
||||||
pkg.srcPath.join('index.tsx').value,
|
|
||||||
{ selfhostPublicPath: '/admin/' }
|
|
||||||
),
|
|
||||||
] as webpack.MultiConfiguration;
|
|
||||||
}
|
|
||||||
case '@affine/web':
|
|
||||||
case '@affine/mobile':
|
|
||||||
case '@affine/ios':
|
|
||||||
case '@affine/android': {
|
|
||||||
const workerConfigs = getBaseWorkerConfigs(
|
|
||||||
pkg,
|
|
||||||
createWebpackWorkerTargetConfig
|
|
||||||
);
|
|
||||||
workerConfigs.push(
|
|
||||||
createWebpackWorkerTargetConfig(
|
|
||||||
pkg,
|
|
||||||
pkg.srcPath.join('nbstore.worker.ts').value
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return [
|
|
||||||
createWebpackHTMLTargetConfig(
|
|
||||||
pkg,
|
|
||||||
pkg.srcPath.join('index.tsx').value,
|
|
||||||
{},
|
|
||||||
workerConfigs.map(config => config.name)
|
|
||||||
),
|
|
||||||
...workerConfigs,
|
|
||||||
] as webpack.MultiConfiguration;
|
|
||||||
}
|
|
||||||
case '@affine/electron-renderer': {
|
|
||||||
const workerConfigs = getBaseWorkerConfigs(
|
|
||||||
pkg,
|
|
||||||
createWebpackWorkerTargetConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
return [
|
|
||||||
createWebpackHTMLTargetConfig(
|
|
||||||
pkg,
|
|
||||||
{
|
|
||||||
index: pkg.srcPath.join('app/index.tsx').value,
|
|
||||||
shell: pkg.srcPath.join('shell/index.tsx').value,
|
|
||||||
popup: pkg.srcPath.join('popup/index.tsx').value,
|
|
||||||
backgroundWorker: pkg.srcPath.join('background-worker/index.ts')
|
|
||||||
.value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
additionalEntryForSelfhost: false,
|
|
||||||
injectGlobalErrorHandler: false,
|
|
||||||
emitAssetsManifest: false,
|
|
||||||
},
|
|
||||||
workerConfigs.map(config => config.name)
|
|
||||||
),
|
|
||||||
...workerConfigs,
|
|
||||||
] as webpack.MultiConfiguration;
|
|
||||||
}
|
|
||||||
case '@affine/server': {
|
|
||||||
return [
|
|
||||||
createWebpackNodeTargetConfig(pkg, pkg.srcPath.join('index.ts').value),
|
|
||||||
] as webpack.MultiConfiguration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(`Unsupported package: ${pkg.name}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRspackBundleConfigs(pkg: Package): MultiRspackOptions {
|
function getRspackBundleConfigs(pkg: Package): MultiRspackOptions {
|
||||||
assertRspackSupportedPackage(pkg);
|
assertRspackSupportedPackage(pkg);
|
||||||
|
|
||||||
@@ -223,13 +140,24 @@ function getRspackBundleConfigs(pkg: Package): MultiRspackOptions {
|
|||||||
createRspackNodeTargetConfig(pkg, pkg.srcPath.join('index.ts').value),
|
createRspackNodeTargetConfig(pkg, pkg.srcPath.join('index.ts').value),
|
||||||
] as MultiRspackOptions;
|
] as MultiRspackOptions;
|
||||||
}
|
}
|
||||||
|
case '@affine/reader': {
|
||||||
|
return [
|
||||||
|
createRspackNodeTargetConfig(pkg, pkg.srcPath.join('index.ts').value, {
|
||||||
|
outputFilename: 'index.js',
|
||||||
|
decoratorVersion: '2022-03',
|
||||||
|
libraryType: 'module',
|
||||||
|
bundleAllDependencies: true,
|
||||||
|
forceExternal: ['yjs'],
|
||||||
|
}),
|
||||||
|
] as MultiRspackOptions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Unsupported package: ${pkg.name}`);
|
throw new Error(`Unsupported package: ${pkg.name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BundleCommand extends PackageCommand {
|
export class BundleCommand extends PackageCommand {
|
||||||
static override paths = [['bundle'], ['webpack'], ['pack'], ['bun']];
|
static override paths = [['bundle'], ['pack'], ['bun']];
|
||||||
|
|
||||||
// bundle is not able to run with deps
|
// bundle is not able to run with deps
|
||||||
override _deps = false;
|
override _deps = false;
|
||||||
@@ -241,123 +169,23 @@ export class BundleCommand extends PackageCommand {
|
|||||||
|
|
||||||
async execute() {
|
async execute() {
|
||||||
const pkg = this.workspace.getPackage(this.package);
|
const pkg = this.workspace.getPackage(this.package);
|
||||||
const bundler = getBundler();
|
|
||||||
|
|
||||||
if (this.dev) {
|
if (this.dev) {
|
||||||
await BundleCommand.dev(pkg, bundler);
|
await BundleCommand.dev(pkg);
|
||||||
} else {
|
} else {
|
||||||
await BundleCommand.build(pkg, bundler);
|
await BundleCommand.build(pkg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async build(pkg: Package, bundler: Bundler = getBundler()) {
|
static async build(pkg: Package) {
|
||||||
if (bundler === 'rspack' && !isRspackSupportedPackageName(pkg.name)) {
|
return BundleCommand.buildWithRspack(pkg);
|
||||||
return BundleCommand.buildWithWebpack(pkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bundler) {
|
|
||||||
case 'webpack':
|
|
||||||
return BundleCommand.buildWithWebpack(pkg);
|
|
||||||
case 'rspack':
|
|
||||||
return BundleCommand.buildWithRspack(pkg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async buildWithWebpack(pkg: Package) {
|
|
||||||
process.env.NODE_ENV = 'production';
|
|
||||||
const logger = new Logger('bundle');
|
|
||||||
logger.info(`Packing package ${pkg.name} with webpack...`);
|
|
||||||
logger.info('Cleaning old output...');
|
|
||||||
rmSync(pkg.distPath.value, { recursive: true, force: true });
|
|
||||||
|
|
||||||
const config = getWebpackBundleConfigs(pkg);
|
|
||||||
config.parallelism = cpus().length;
|
|
||||||
|
|
||||||
const compiler = webpack(config);
|
|
||||||
if (!compiler) {
|
|
||||||
throw new Error('Failed to create webpack compiler');
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const stats = await new Promise<webpack.Stats | webpack.MultiStats>(
|
|
||||||
(resolve, reject) => {
|
|
||||||
compiler.run((error, stats) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!stats) {
|
|
||||||
reject(new Error('Failed to get webpack stats'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resolve(stats);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (stats.hasErrors()) {
|
|
||||||
console.error(stats.toString('errors-only'));
|
|
||||||
process.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log(stats.toString('minimal'));
|
|
||||||
await uploadAssetsForPackage(pkg, logger);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async dev(
|
static async dev(
|
||||||
pkg: Package,
|
pkg: Package,
|
||||||
bundler: Bundler = getBundler(),
|
devServerConfig?: RspackDevServerConfiguration
|
||||||
devServerConfig?:
|
|
||||||
| WebpackDevServerConfiguration
|
|
||||||
| RspackDevServerConfiguration
|
|
||||||
) {
|
) {
|
||||||
if (bundler === 'rspack' && !isRspackSupportedPackageName(pkg.name)) {
|
return BundleCommand.devWithRspack(pkg, devServerConfig);
|
||||||
return BundleCommand.devWithWebpack(
|
|
||||||
pkg,
|
|
||||||
devServerConfig as WebpackDevServerConfiguration | undefined
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bundler) {
|
|
||||||
case 'webpack':
|
|
||||||
return BundleCommand.devWithWebpack(
|
|
||||||
pkg,
|
|
||||||
devServerConfig as WebpackDevServerConfiguration | undefined
|
|
||||||
);
|
|
||||||
case 'rspack':
|
|
||||||
return BundleCommand.devWithRspack(
|
|
||||||
pkg,
|
|
||||||
devServerConfig as RspackDevServerConfiguration | undefined
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async devWithWebpack(
|
|
||||||
pkg: Package,
|
|
||||||
devServerConfig?: WebpackDevServerConfiguration
|
|
||||||
) {
|
|
||||||
process.env.NODE_ENV = 'development';
|
|
||||||
const logger = new Logger('bundle');
|
|
||||||
logger.info(`Starting webpack dev server for ${pkg.name}...`);
|
|
||||||
|
|
||||||
const config = getWebpackBundleConfigs(pkg);
|
|
||||||
config.parallelism = cpus().length;
|
|
||||||
|
|
||||||
const compiler = webpack(config);
|
|
||||||
if (!compiler) {
|
|
||||||
throw new Error('Failed to create webpack compiler');
|
|
||||||
}
|
|
||||||
|
|
||||||
const devServer = new WebpackDevServer(
|
|
||||||
merge({}, DEFAULT_DEV_SERVER_CONFIG, devServerConfig),
|
|
||||||
compiler
|
|
||||||
);
|
|
||||||
|
|
||||||
await devServer.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async buildWithRspack(pkg: Package) {
|
static async buildWithRspack(pkg: Package) {
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
export const SUPPORTED_BUNDLERS = ['webpack', 'rspack'] as const;
|
|
||||||
|
|
||||||
export type Bundler = (typeof SUPPORTED_BUNDLERS)[number];
|
|
||||||
|
|
||||||
export const DEFAULT_BUNDLER: Bundler = 'rspack';
|
|
||||||
|
|
||||||
function isBundler(value: string): value is Bundler {
|
|
||||||
return SUPPORTED_BUNDLERS.includes(value as Bundler);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function normalizeBundler(input: string | undefined | null): Bundler {
|
|
||||||
const value = input?.trim().toLowerCase();
|
|
||||||
if (!value) {
|
|
||||||
return DEFAULT_BUNDLER;
|
|
||||||
}
|
|
||||||
if (isBundler(value)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(
|
|
||||||
`Unsupported AFFINE_BUNDLER: "${input}". Expected one of: ${SUPPORTED_BUNDLERS.join(', ')}.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getBundler(env: NodeJS.ProcessEnv = process.env): Bundler {
|
|
||||||
return normalizeBundler(env.AFFINE_BUNDLER);
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
(function () {
|
(function () {
|
||||||
var errorEl = null;
|
let errorEl = null;
|
||||||
function showGlobalErrorPage() {
|
function showGlobalErrorPage() {
|
||||||
if (errorEl) {
|
if (errorEl) {
|
||||||
return;
|
return;
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
* @param event {PromiseRejectionEvent|ErrorEvent}
|
* @param event {PromiseRejectionEvent|ErrorEvent}
|
||||||
*/
|
*/
|
||||||
function handler(event) {
|
function handler(event) {
|
||||||
var error;
|
let error;
|
||||||
|
|
||||||
if ('error' in event) {
|
if ('error' in event) {
|
||||||
error =
|
error =
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
console.error('unhandled unrecoverable error', error);
|
console.error('unhandled unrecoverable error', error);
|
||||||
|
|
||||||
var shouldCache =
|
const shouldCache =
|
||||||
// syntax error
|
// syntax error
|
||||||
error && error instanceof SyntaxError;
|
error && error instanceof SyntaxError;
|
||||||
|
|
||||||
@@ -79,9 +79,9 @@
|
|||||||
|
|
||||||
function unregisterRegisterGlobalErrorHandler(fn) {
|
function unregisterRegisterGlobalErrorHandler(fn) {
|
||||||
if (typeof fn === 'function') {
|
if (typeof fn === 'function') {
|
||||||
var app = document.getElementById('app');
|
const app = document.getElementById('app');
|
||||||
if (app) {
|
if (app) {
|
||||||
var ob = new MutationObserver(function () {
|
let ob = new MutationObserver(function () {
|
||||||
fn();
|
fn();
|
||||||
ob.disconnect();
|
ob.disconnect();
|
||||||
ob = null;
|
ob = null;
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ensureBasicEnvironment() {
|
function ensureBasicEnvironment() {
|
||||||
var globals = [
|
const globals = [
|
||||||
'Promise',
|
'Promise',
|
||||||
'Map',
|
'Map',
|
||||||
'fetch',
|
'fetch',
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
||||||
for (var i = 0; i < globals.length; i++) {
|
for (let i = 0; i < globals.length; i++) {
|
||||||
if (!(globals[i] in globalThis)) {
|
if (!(globals[i] in globalThis)) {
|
||||||
showGlobalErrorPage();
|
showGlobalErrorPage();
|
||||||
return;
|
return;
|
||||||
@@ -111,6 +111,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensureBasicEnvironment();
|
ensureBasicEnvironment();
|
||||||
var goodtogo = registerGlobalErrorHandler();
|
const goodtogo = registerGlobalErrorHandler();
|
||||||
unregisterRegisterGlobalErrorHandler(goodtogo);
|
unregisterRegisterGlobalErrorHandler(goodtogo);
|
||||||
})();
|
})();
|
||||||
@@ -5,7 +5,10 @@ import { Path, ProjectRoot } from '@affine-tools/utils/path';
|
|||||||
import { Repository } from '@napi-rs/simple-git';
|
import { Repository } from '@napi-rs/simple-git';
|
||||||
import HTMLPlugin from 'html-webpack-plugin';
|
import HTMLPlugin from 'html-webpack-plugin';
|
||||||
import { once } from 'lodash-es';
|
import { once } from 'lodash-es';
|
||||||
import type { WebpackPluginInstance } from 'webpack';
|
|
||||||
|
type PluginLike = {
|
||||||
|
apply: (compiler: CompilerLike) => void;
|
||||||
|
};
|
||||||
|
|
||||||
type CompilerLike = {
|
type CompilerLike = {
|
||||||
webpack?: {
|
webpack?: {
|
||||||
@@ -204,12 +207,12 @@ const CorsPlugin = {
|
|||||||
export function createHTMLPlugins(
|
export function createHTMLPlugins(
|
||||||
BUILD_CONFIG: BUILD_CONFIG_TYPE,
|
BUILD_CONFIG: BUILD_CONFIG_TYPE,
|
||||||
config: CreateHTMLPluginConfig
|
config: CreateHTMLPluginConfig
|
||||||
): WebpackPluginInstance[] {
|
): (HTMLPlugin | PluginLike)[] {
|
||||||
const publicPath = getPublicPath(BUILD_CONFIG);
|
const publicPath = getPublicPath(BUILD_CONFIG);
|
||||||
const htmlPluginOptions = getHTMLPluginOptions(BUILD_CONFIG);
|
const htmlPluginOptions = getHTMLPluginOptions(BUILD_CONFIG);
|
||||||
const selfhostPublicPath = config.selfhostPublicPath ?? '/';
|
const selfhostPublicPath = config.selfhostPublicPath ?? '/';
|
||||||
|
|
||||||
const plugins: WebpackPluginInstance[] = [];
|
const plugins: (HTMLPlugin | PluginLike)[] = [];
|
||||||
plugins.push(
|
plugins.push(
|
||||||
new HTMLPlugin({
|
new HTMLPlugin({
|
||||||
...htmlPluginOptions,
|
...htmlPluginOptions,
|
||||||
@@ -7,21 +7,51 @@ import { Package } from '@affine-tools/utils/workspace';
|
|||||||
import rspack, {
|
import rspack, {
|
||||||
type Configuration as RspackConfiguration,
|
type Configuration as RspackConfiguration,
|
||||||
} from '@rspack/core';
|
} from '@rspack/core';
|
||||||
import { sentryWebpackPlugin } from '@sentry/webpack-plugin';
|
import type { sentryWebpackPlugin as SentryWebpackPluginFactory } from '@sentry/webpack-plugin';
|
||||||
import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin';
|
import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin';
|
||||||
import cssnano from 'cssnano';
|
import cssnano from 'cssnano';
|
||||||
import { compact, merge } from 'lodash-es';
|
import { compact, merge } from 'lodash-es';
|
||||||
|
|
||||||
import { queuedashScopePostcssPlugin } from '../postcss/queuedash-scope.js';
|
import { queuedashScopePostcssPlugin } from '../postcss/queuedash-scope.js';
|
||||||
import { productionCacheGroups } from '../webpack/cache-group.js';
|
import { productionCacheGroups } from '../rspack-shared/cache-group.js';
|
||||||
import {
|
import {
|
||||||
type CreateHTMLPluginConfig,
|
type CreateHTMLPluginConfig,
|
||||||
createHTMLPlugins as createWebpackCompatibleHTMLPlugins,
|
createHTMLPlugins,
|
||||||
} from '../webpack/html-plugin.js';
|
} from '../rspack-shared/html-plugin.js';
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
const IN_CI = !!process.env.CI;
|
const IN_CI = !!process.env.CI;
|
||||||
|
const hasSentryBuildEnvs = () =>
|
||||||
|
!!(
|
||||||
|
process.env.SENTRY_AUTH_TOKEN &&
|
||||||
|
process.env.SENTRY_ORG &&
|
||||||
|
process.env.SENTRY_PROJECT
|
||||||
|
);
|
||||||
|
|
||||||
|
function createSentryPlugin() {
|
||||||
|
if (!hasSentryBuildEnvs()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { sentryWebpackPlugin } = require('@sentry/webpack-plugin') as {
|
||||||
|
sentryWebpackPlugin: typeof SentryWebpackPluginFactory;
|
||||||
|
};
|
||||||
|
|
||||||
|
return sentryWebpackPlugin({
|
||||||
|
org: process.env.SENTRY_ORG!,
|
||||||
|
project: process.env.SENTRY_PROJECT!,
|
||||||
|
authToken: process.env.SENTRY_AUTH_TOKEN!,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
const reason =
|
||||||
|
error instanceof Error ? error.message : 'unknown load error';
|
||||||
|
throw new Error(
|
||||||
|
`Failed to load @sentry/webpack-plugin while SENTRY_* envs are set: ${reason}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const availableChannels = ['canary', 'beta', 'stable', 'internal'];
|
const availableChannels = ['canary', 'beta', 'stable', 'internal'];
|
||||||
function getBuildConfigFromEnv(pkg: Package) {
|
function getBuildConfigFromEnv(pkg: Package) {
|
||||||
@@ -73,7 +103,7 @@ export function createHTMLTargetConfig(
|
|||||||
console.log(`Config: ${JSON.stringify(buildConfig, null, 2)}`);
|
console.log(`Config: ${JSON.stringify(buildConfig, null, 2)}`);
|
||||||
|
|
||||||
const config: RspackConfiguration = {
|
const config: RspackConfiguration = {
|
||||||
//#region basic webpack config
|
//#region basic bundler config
|
||||||
name: entry['index'],
|
name: entry['index'],
|
||||||
dependencies: deps,
|
dependencies: deps,
|
||||||
context: ProjectRoot.value,
|
context: ProjectRoot.value,
|
||||||
@@ -253,7 +283,7 @@ export function createHTMLTargetConfig(
|
|||||||
//#region plugins
|
//#region plugins
|
||||||
plugins: compact([
|
plugins: compact([
|
||||||
!IN_CI && new rspack.ProgressPlugin(),
|
!IN_CI && new rspack.ProgressPlugin(),
|
||||||
...createWebpackCompatibleHTMLPlugins(buildConfig, htmlConfig),
|
...createHTMLPlugins(buildConfig, htmlConfig),
|
||||||
new rspack.DefinePlugin({
|
new rspack.DefinePlugin({
|
||||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
||||||
...Object.entries(buildConfig).reduce(
|
...Object.entries(buildConfig).reduce(
|
||||||
@@ -280,14 +310,7 @@ export function createHTMLTargetConfig(
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
process.env.SENTRY_AUTH_TOKEN &&
|
createSentryPlugin(),
|
||||||
process.env.SENTRY_ORG &&
|
|
||||||
process.env.SENTRY_PROJECT &&
|
|
||||||
sentryWebpackPlugin({
|
|
||||||
org: process.env.SENTRY_ORG,
|
|
||||||
project: process.env.SENTRY_PROJECT,
|
|
||||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
||||||
}),
|
|
||||||
// sourcemap url like # sourceMappingURL=76-6370cd185962bc89.js.map wont load in electron
|
// sourcemap url like # sourceMappingURL=76-6370cd185962bc89.js.map wont load in electron
|
||||||
// this is because the default file:// protocol will be ignored by Chromium
|
// this is because the default file:// protocol will be ignored by Chromium
|
||||||
// so we need to replace the sourceMappingURL to assets:// protocol
|
// so we need to replace the sourceMappingURL to assets:// protocol
|
||||||
@@ -470,14 +493,7 @@ export function createWorkerTargetConfig(
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
new rspack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
|
new rspack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
|
||||||
process.env.SENTRY_AUTH_TOKEN &&
|
createSentryPlugin(),
|
||||||
process.env.SENTRY_ORG &&
|
|
||||||
process.env.SENTRY_PROJECT &&
|
|
||||||
sentryWebpackPlugin({
|
|
||||||
org: process.env.SENTRY_ORG,
|
|
||||||
project: process.env.SENTRY_PROJECT,
|
|
||||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
||||||
}),
|
|
||||||
]),
|
]),
|
||||||
stats: { errorDetails: true },
|
stats: { errorDetails: true },
|
||||||
optimization: {
|
optimization: {
|
||||||
@@ -506,9 +522,18 @@ export function createWorkerTargetConfig(
|
|||||||
|
|
||||||
export function createNodeTargetConfig(
|
export function createNodeTargetConfig(
|
||||||
pkg: Package,
|
pkg: Package,
|
||||||
entry: string
|
entry: string,
|
||||||
|
options: {
|
||||||
|
outputFilename?: string;
|
||||||
|
decoratorVersion?: 'legacy' | '2022-03';
|
||||||
|
libraryType?: 'module' | 'commonjs2';
|
||||||
|
bundleAllDependencies?: boolean;
|
||||||
|
forceExternal?: string[];
|
||||||
|
} = {}
|
||||||
): Omit<RspackConfiguration, 'name'> & { name: string } {
|
): Omit<RspackConfiguration, 'name'> & { name: string } {
|
||||||
const dev = process.env.NODE_ENV === 'development';
|
const dev = process.env.NODE_ENV === 'development';
|
||||||
|
const useLegacyDecorator = options.decoratorVersion !== '2022-03';
|
||||||
|
const forceExternal = options.forceExternal ?? [];
|
||||||
return {
|
return {
|
||||||
name: entry,
|
name: entry,
|
||||||
context: ProjectRoot.value,
|
context: ProjectRoot.value,
|
||||||
@@ -519,17 +544,28 @@ export function createNodeTargetConfig(
|
|||||||
},
|
},
|
||||||
entry: { index: entry },
|
entry: { index: entry },
|
||||||
output: {
|
output: {
|
||||||
filename: `main.js`,
|
filename: options.outputFilename ?? 'main.js',
|
||||||
path: pkg.distPath.value,
|
path: pkg.distPath.value,
|
||||||
clean: true,
|
clean: true,
|
||||||
globalObject: 'globalThis',
|
globalObject: 'globalThis',
|
||||||
|
...(options.libraryType
|
||||||
|
? { library: { type: options.libraryType } }
|
||||||
|
: {}),
|
||||||
},
|
},
|
||||||
target: ['node', 'es2022'],
|
target: ['node', 'es2022'],
|
||||||
externals: ((data: any, callback: (err: null, value: boolean) => void) => {
|
externals: ((data: any, callback: (err: null, value: boolean) => void) => {
|
||||||
if (
|
if (
|
||||||
|
data.request &&
|
||||||
|
forceExternal.some(
|
||||||
|
dep => data.request === dep || data.request.startsWith(`${dep}/`)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
callback(null, true);
|
||||||
|
} else if (
|
||||||
data.request &&
|
data.request &&
|
||||||
// import ... from 'module'
|
// import ... from 'module'
|
||||||
/^[a-zA-Z@]/.test(data.request) &&
|
/^[a-zA-Z@]/.test(data.request) &&
|
||||||
|
!options.bundleAllDependencies &&
|
||||||
// not workspace deps
|
// not workspace deps
|
||||||
!pkg.deps.some(dep => data.request!.startsWith(dep.name))
|
!pkg.deps.some(dep => data.request!.startsWith(dep.name))
|
||||||
) {
|
) {
|
||||||
@@ -561,8 +597,9 @@ export function createNodeTargetConfig(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.node$/,
|
test: /\.node$/,
|
||||||
loader: Path.dir(import.meta.url).join('../webpack/node-loader.js')
|
loader: Path.dir(import.meta.url).join(
|
||||||
.value,
|
'../rspack-shared/node-loader.js'
|
||||||
|
).value,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.tsx?$/,
|
test: /\.tsx?$/,
|
||||||
@@ -582,8 +619,15 @@ export function createNodeTargetConfig(
|
|||||||
target: 'es2022',
|
target: 'es2022',
|
||||||
externalHelpers: false,
|
externalHelpers: false,
|
||||||
transform: {
|
transform: {
|
||||||
legacyDecorator: true,
|
...(useLegacyDecorator
|
||||||
decoratorMetadata: true,
|
? {
|
||||||
|
legacyDecorator: true,
|
||||||
|
decoratorMetadata: true,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
useDefineForClassFields: false,
|
||||||
|
decoratorVersion: '2022-03',
|
||||||
|
}),
|
||||||
react: { runtime: 'automatic' },
|
react: { runtime: 'automatic' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export class RunCommand extends PackageCommand {
|
|||||||
|
|
||||||
\`affine init\` Generate the required files if there are any package added or removed
|
\`affine init\` Generate the required files if there are any package added or removed
|
||||||
|
|
||||||
\`affine clean\` Clean the output files of ts, cargo, webpack, etc.
|
\`affine clean\` Clean the output files of ts, cargo, bundler outputs, etc.
|
||||||
|
|
||||||
\`affine bundle\` Bundle the packages
|
\`affine bundle\` Bundle the packages
|
||||||
|
|
||||||
|
|||||||
@@ -1,639 +0,0 @@
|
|||||||
import { createRequire } from 'node:module';
|
|
||||||
import path from 'node:path';
|
|
||||||
|
|
||||||
import { getBuildConfig } from '@affine-tools/utils/build-config';
|
|
||||||
import { Path, ProjectRoot } from '@affine-tools/utils/path';
|
|
||||||
import { Package } from '@affine-tools/utils/workspace';
|
|
||||||
import { PerfseePlugin } from '@perfsee/webpack';
|
|
||||||
import { sentryWebpackPlugin } from '@sentry/webpack-plugin';
|
|
||||||
import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin';
|
|
||||||
import CopyPlugin from 'copy-webpack-plugin';
|
|
||||||
import { compact, merge } from 'lodash-es';
|
|
||||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
|
||||||
import TerserPlugin from 'terser-webpack-plugin';
|
|
||||||
import webpack from 'webpack';
|
|
||||||
|
|
||||||
import { queuedashScopePostcssPlugin } from '../postcss/queuedash-scope.js';
|
|
||||||
import { productionCacheGroups } from './cache-group.js';
|
|
||||||
import {
|
|
||||||
type CreateHTMLPluginConfig,
|
|
||||||
createHTMLPlugins,
|
|
||||||
} from './html-plugin.js';
|
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
|
||||||
const cssnano = require('cssnano');
|
|
||||||
|
|
||||||
const IN_CI = !!process.env.CI;
|
|
||||||
|
|
||||||
const availableChannels = ['canary', 'beta', 'stable', 'internal'];
|
|
||||||
function getBuildConfigFromEnv(pkg: Package) {
|
|
||||||
const channel = process.env.BUILD_TYPE ?? 'canary';
|
|
||||||
const dev = process.env.NODE_ENV === 'development';
|
|
||||||
if (!availableChannels.includes(channel)) {
|
|
||||||
throw new Error(
|
|
||||||
`BUILD_TYPE must be one of ${availableChannels.join(', ')}, received [${channel}]`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getBuildConfig(pkg, {
|
|
||||||
// @ts-expect-error checked
|
|
||||||
channel,
|
|
||||||
mode: dev ? 'development' : 'production',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createHTMLTargetConfig(
|
|
||||||
pkg: Package,
|
|
||||||
entry: string | Record<string, string>,
|
|
||||||
htmlConfig: Partial<CreateHTMLPluginConfig> = {},
|
|
||||||
deps?: string[]
|
|
||||||
): webpack.Configuration {
|
|
||||||
entry = typeof entry === 'string' ? { index: entry } : entry;
|
|
||||||
|
|
||||||
htmlConfig = merge(
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
filename: 'index.html',
|
|
||||||
additionalEntryForSelfhost: true,
|
|
||||||
injectGlobalErrorHandler: true,
|
|
||||||
emitAssetsManifest: true,
|
|
||||||
},
|
|
||||||
htmlConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildConfig = getBuildConfigFromEnv(pkg);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Building [${pkg.name}] for [${buildConfig.appBuildType}] channel in [${buildConfig.debug ? 'development' : 'production'}] mode.`
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`Entry points: ${Object.entries(entry)
|
|
||||||
.map(([name, path]) => `${name}: ${path}`)
|
|
||||||
.join(', ')}`
|
|
||||||
);
|
|
||||||
console.log(`Output path: ${pkg.distPath.value}`);
|
|
||||||
console.log(`Config: ${JSON.stringify(buildConfig, null, 2)}`);
|
|
||||||
|
|
||||||
const config: webpack.Configuration = {
|
|
||||||
//#region basic webpack config
|
|
||||||
name: entry['index'],
|
|
||||||
dependencies: deps,
|
|
||||||
context: ProjectRoot.value,
|
|
||||||
experiments: {
|
|
||||||
topLevelAwait: true,
|
|
||||||
outputModule: false,
|
|
||||||
syncWebAssembly: true,
|
|
||||||
},
|
|
||||||
entry,
|
|
||||||
output: {
|
|
||||||
environment: { module: true, dynamicImport: true },
|
|
||||||
filename: buildConfig.debug
|
|
||||||
? 'js/[name].js'
|
|
||||||
: 'js/[name].[contenthash:8].js',
|
|
||||||
assetModuleFilename: buildConfig.debug
|
|
||||||
? '[name].[contenthash:8][ext]'
|
|
||||||
: 'assets/[name].[contenthash:8][ext][query]',
|
|
||||||
path: pkg.distPath.value,
|
|
||||||
clean: false,
|
|
||||||
globalObject: 'globalThis',
|
|
||||||
// NOTE(@forehalo): always keep it '/'
|
|
||||||
publicPath: '/',
|
|
||||||
},
|
|
||||||
target: ['web', 'es2022'],
|
|
||||||
mode: buildConfig.debug ? 'development' : 'production',
|
|
||||||
devtool: buildConfig.debug ? 'cheap-module-source-map' : 'source-map',
|
|
||||||
resolve: {
|
|
||||||
symlinks: true,
|
|
||||||
extensionAlias: {
|
|
||||||
'.js': ['.js', '.tsx', '.ts'],
|
|
||||||
'.mjs': ['.mjs', '.mts'],
|
|
||||||
},
|
|
||||||
extensions: ['.js', '.ts', '.tsx'],
|
|
||||||
alias: {
|
|
||||||
yjs: ProjectRoot.join('node_modules', 'yjs').value,
|
|
||||||
lit: ProjectRoot.join('node_modules', 'lit').value,
|
|
||||||
'@preact/signals-core': ProjectRoot.join(
|
|
||||||
'node_modules',
|
|
||||||
'@preact',
|
|
||||||
'signals-core'
|
|
||||||
).value,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region module config
|
|
||||||
module: {
|
|
||||||
parser: {
|
|
||||||
javascript: {
|
|
||||||
// Do not mock Node.js globals
|
|
||||||
node: false,
|
|
||||||
requireJs: false,
|
|
||||||
import: true,
|
|
||||||
// Treat as missing export as error
|
|
||||||
strictExportPresence: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
//#region rules
|
|
||||||
rules: [
|
|
||||||
{ test: /\.m?js?$/, resolve: { fullySpecified: false } },
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
enforce: 'pre',
|
|
||||||
include: /@blocksuite/,
|
|
||||||
use: ['source-map-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oneOf: [
|
|
||||||
{
|
|
||||||
test: /\.ts$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
loader: 'swc-loader',
|
|
||||||
options: {
|
|
||||||
// https://swc.rs/docs/configuring-swc/
|
|
||||||
jsc: {
|
|
||||||
preserveAllComments: true,
|
|
||||||
parser: {
|
|
||||||
syntax: 'typescript',
|
|
||||||
dynamicImport: true,
|
|
||||||
topLevelAwait: false,
|
|
||||||
tsx: false,
|
|
||||||
decorators: true,
|
|
||||||
},
|
|
||||||
target: 'es2022',
|
|
||||||
externalHelpers: false,
|
|
||||||
transform: {
|
|
||||||
useDefineForClassFields: false,
|
|
||||||
decoratorVersion: '2022-03',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sourceMaps: true,
|
|
||||||
inlineSourcesContent: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.tsx$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
loader: 'swc-loader',
|
|
||||||
options: {
|
|
||||||
// https://swc.rs/docs/configuring-swc/
|
|
||||||
jsc: {
|
|
||||||
preserveAllComments: true,
|
|
||||||
parser: {
|
|
||||||
syntax: 'typescript',
|
|
||||||
dynamicImport: true,
|
|
||||||
topLevelAwait: false,
|
|
||||||
tsx: true,
|
|
||||||
decorators: true,
|
|
||||||
},
|
|
||||||
target: 'es2022',
|
|
||||||
externalHelpers: false,
|
|
||||||
transform: {
|
|
||||||
react: { runtime: 'automatic' },
|
|
||||||
useDefineForClassFields: false,
|
|
||||||
decoratorVersion: '2022-03',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sourceMaps: true,
|
|
||||||
inlineSourcesContent: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(png|jpg|gif|svg|webp|mp4|zip)$/,
|
|
||||||
type: 'asset/resource',
|
|
||||||
},
|
|
||||||
{ test: /\.(ttf|eot|woff|woff2)$/, type: 'asset/resource' },
|
|
||||||
{ test: /\.txt$/, type: 'asset/source' },
|
|
||||||
{ test: /\.inline\.svg$/, type: 'asset/inline' },
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: [
|
|
||||||
buildConfig.debug
|
|
||||||
? 'style-loader'
|
|
||||||
: MiniCssExtractPlugin.loader,
|
|
||||||
{
|
|
||||||
loader: 'css-loader',
|
|
||||||
options: {
|
|
||||||
url: true,
|
|
||||||
sourceMap: false,
|
|
||||||
modules: false,
|
|
||||||
import: true,
|
|
||||||
importLoaders: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: 'postcss-loader',
|
|
||||||
options: {
|
|
||||||
postcssOptions: {
|
|
||||||
plugins: pkg.join('tailwind.config.js').exists()
|
|
||||||
? [
|
|
||||||
[
|
|
||||||
'@tailwindcss/postcss',
|
|
||||||
require(pkg.join('tailwind.config.js').value),
|
|
||||||
],
|
|
||||||
['autoprefixer'],
|
|
||||||
...(buildConfig.isAdmin
|
|
||||||
? [queuedashScopePostcssPlugin()]
|
|
||||||
: []),
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
cssnano({
|
|
||||||
preset: ['default', { convertValues: false }],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
//#endregion
|
|
||||||
},
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region plugins
|
|
||||||
plugins: compact([
|
|
||||||
!IN_CI && new webpack.ProgressPlugin({ percentBy: 'entries' }),
|
|
||||||
...createHTMLPlugins(buildConfig, htmlConfig),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
|
||||||
...Object.entries(buildConfig).reduce(
|
|
||||||
(def, [k, v]) => {
|
|
||||||
def[`BUILD_CONFIG.${k}`] = JSON.stringify(v);
|
|
||||||
return def;
|
|
||||||
},
|
|
||||||
{} as Record<string, string>
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
!buildConfig.debug &&
|
|
||||||
// todo: support multiple entry points
|
|
||||||
new MiniCssExtractPlugin({
|
|
||||||
filename: `[name].[contenthash:8].css`,
|
|
||||||
ignoreOrder: true,
|
|
||||||
}),
|
|
||||||
new VanillaExtractPlugin(),
|
|
||||||
!buildConfig.isAdmin &&
|
|
||||||
new CopyPlugin({
|
|
||||||
patterns: [
|
|
||||||
{
|
|
||||||
// copy the shared public assets into dist
|
|
||||||
from: new Package('@affine/core').join('public').value,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
!buildConfig.debug &&
|
|
||||||
process.env.PERFSEE_TOKEN &&
|
|
||||||
new PerfseePlugin({ project: 'affine-toeverything' }),
|
|
||||||
process.env.SENTRY_AUTH_TOKEN &&
|
|
||||||
process.env.SENTRY_ORG &&
|
|
||||||
process.env.SENTRY_PROJECT &&
|
|
||||||
sentryWebpackPlugin({
|
|
||||||
org: process.env.SENTRY_ORG,
|
|
||||||
project: process.env.SENTRY_PROJECT,
|
|
||||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
||||||
}),
|
|
||||||
// sourcemap url like # sourceMappingURL=76-6370cd185962bc89.js.map wont load in electron
|
|
||||||
// this is because the default file:// protocol will be ignored by Chromium
|
|
||||||
// so we need to replace the sourceMappingURL to assets:// protocol
|
|
||||||
// for example:
|
|
||||||
// replace # sourceMappingURL=76-6370cd185962bc89.js.map
|
|
||||||
// to # sourceMappingURL=assets://./{dir}/76-6370cd185962bc89.js.map
|
|
||||||
buildConfig.isElectron &&
|
|
||||||
new webpack.SourceMapDevToolPlugin({
|
|
||||||
append: pathData => {
|
|
||||||
return `\n//# sourceMappingURL=assets://./${pathData.filename}.map`;
|
|
||||||
},
|
|
||||||
filename: '[file].map',
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
stats: { errorDetails: true },
|
|
||||||
|
|
||||||
//#region optimization
|
|
||||||
optimization: {
|
|
||||||
minimize: !buildConfig.debug,
|
|
||||||
minimizer: [
|
|
||||||
new TerserPlugin({
|
|
||||||
minify: TerserPlugin.swcMinify,
|
|
||||||
parallel: true,
|
|
||||||
extractComments: true,
|
|
||||||
terserOptions: {
|
|
||||||
ecma: 2020,
|
|
||||||
compress: { unused: true },
|
|
||||||
mangle: { keep_classnames: true },
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
removeEmptyChunks: true,
|
|
||||||
providedExports: true,
|
|
||||||
usedExports: true,
|
|
||||||
sideEffects: true,
|
|
||||||
removeAvailableModules: true,
|
|
||||||
runtimeChunk: { name: 'runtime' },
|
|
||||||
splitChunks: {
|
|
||||||
chunks: 'all',
|
|
||||||
minSize: 1,
|
|
||||||
minChunks: 1,
|
|
||||||
maxInitialRequests: Number.MAX_SAFE_INTEGER,
|
|
||||||
maxAsyncRequests: Number.MAX_SAFE_INTEGER,
|
|
||||||
cacheGroups: productionCacheGroups,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
//#endregion
|
|
||||||
};
|
|
||||||
|
|
||||||
if (buildConfig.debug && !IN_CI) {
|
|
||||||
config.optimization = {
|
|
||||||
...config.optimization,
|
|
||||||
minimize: false,
|
|
||||||
runtimeChunk: false,
|
|
||||||
splitChunks: {
|
|
||||||
maxInitialRequests: Infinity,
|
|
||||||
chunks: 'all',
|
|
||||||
cacheGroups: {
|
|
||||||
defaultVendors: {
|
|
||||||
test: `[\\/]node_modules[\\/](?!.*vanilla-extract)`,
|
|
||||||
priority: -10,
|
|
||||||
reuseExistingChunk: true,
|
|
||||||
},
|
|
||||||
default: { minChunks: 2, priority: -20, reuseExistingChunk: true },
|
|
||||||
styles: {
|
|
||||||
name: 'styles',
|
|
||||||
type: 'css/mini-extract',
|
|
||||||
chunks: 'all',
|
|
||||||
enforce: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createWorkerTargetConfig(
|
|
||||||
pkg: Package,
|
|
||||||
entry: string
|
|
||||||
): Omit<webpack.Configuration, 'name'> & { name: string } {
|
|
||||||
const workerName = path.basename(entry).replace(/\.worker\.ts$/, '');
|
|
||||||
const buildConfig = getBuildConfigFromEnv(pkg);
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: entry,
|
|
||||||
context: ProjectRoot.value,
|
|
||||||
experiments: {
|
|
||||||
topLevelAwait: true,
|
|
||||||
outputModule: false,
|
|
||||||
syncWebAssembly: true,
|
|
||||||
},
|
|
||||||
entry: { [workerName]: entry },
|
|
||||||
output: {
|
|
||||||
filename: `js/${workerName}-${buildConfig.appVersion}.worker.js`,
|
|
||||||
path: pkg.distPath.value,
|
|
||||||
clean: false,
|
|
||||||
globalObject: 'globalThis',
|
|
||||||
// NOTE(@forehalo): always keep it '/'
|
|
||||||
publicPath: '/',
|
|
||||||
},
|
|
||||||
target: ['webworker', 'es2022'],
|
|
||||||
mode: buildConfig.debug ? 'development' : 'production',
|
|
||||||
devtool: buildConfig.debug ? 'cheap-module-source-map' : 'source-map',
|
|
||||||
resolve: {
|
|
||||||
symlinks: true,
|
|
||||||
extensionAlias: { '.js': ['.js', '.ts'], '.mjs': ['.mjs', '.mts'] },
|
|
||||||
extensions: ['.js', '.ts'],
|
|
||||||
alias: { yjs: ProjectRoot.join('node_modules', 'yjs').value },
|
|
||||||
},
|
|
||||||
|
|
||||||
module: {
|
|
||||||
parser: {
|
|
||||||
javascript: {
|
|
||||||
// Do not mock Node.js globals
|
|
||||||
node: false,
|
|
||||||
requireJs: false,
|
|
||||||
import: true,
|
|
||||||
// Treat as missing export as error
|
|
||||||
strictExportPresence: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rules: [
|
|
||||||
{ test: /\.m?js?$/, resolve: { fullySpecified: false } },
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
enforce: 'pre',
|
|
||||||
include: /@blocksuite/,
|
|
||||||
use: ['source-map-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oneOf: [
|
|
||||||
{
|
|
||||||
test: /\.ts$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
loader: 'swc-loader',
|
|
||||||
options: {
|
|
||||||
// https://swc.rs/docs/configuring-swc/
|
|
||||||
jsc: {
|
|
||||||
preserveAllComments: true,
|
|
||||||
parser: {
|
|
||||||
syntax: 'typescript',
|
|
||||||
dynamicImport: true,
|
|
||||||
topLevelAwait: false,
|
|
||||||
tsx: false,
|
|
||||||
decorators: true,
|
|
||||||
},
|
|
||||||
target: 'es2022',
|
|
||||||
externalHelpers: false,
|
|
||||||
transform: {
|
|
||||||
useDefineForClassFields: false,
|
|
||||||
decoratorVersion: '2022-03',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sourceMaps: true,
|
|
||||||
inlineSourcesContent: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
plugins: compact([
|
|
||||||
new webpack.DefinePlugin(
|
|
||||||
Object.entries(buildConfig).reduce(
|
|
||||||
(def, [k, v]) => {
|
|
||||||
def[`BUILD_CONFIG.${k}`] = JSON.stringify(v);
|
|
||||||
return def;
|
|
||||||
},
|
|
||||||
{} as Record<string, string>
|
|
||||||
)
|
|
||||||
),
|
|
||||||
new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
|
|
||||||
process.env.SENTRY_AUTH_TOKEN &&
|
|
||||||
process.env.SENTRY_ORG &&
|
|
||||||
process.env.SENTRY_PROJECT &&
|
|
||||||
sentryWebpackPlugin({
|
|
||||||
org: process.env.SENTRY_ORG,
|
|
||||||
project: process.env.SENTRY_PROJECT,
|
|
||||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
stats: { errorDetails: true },
|
|
||||||
optimization: {
|
|
||||||
minimize: !buildConfig.debug,
|
|
||||||
minimizer: [
|
|
||||||
new TerserPlugin({
|
|
||||||
minify: TerserPlugin.swcMinify,
|
|
||||||
parallel: true,
|
|
||||||
extractComments: true,
|
|
||||||
terserOptions: {
|
|
||||||
ecma: 2020,
|
|
||||||
compress: { unused: true },
|
|
||||||
mangle: { keep_classnames: true },
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
removeEmptyChunks: true,
|
|
||||||
providedExports: true,
|
|
||||||
usedExports: true,
|
|
||||||
sideEffects: true,
|
|
||||||
removeAvailableModules: true,
|
|
||||||
runtimeChunk: false,
|
|
||||||
splitChunks: false,
|
|
||||||
},
|
|
||||||
performance: { hints: false },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createNodeTargetConfig(
|
|
||||||
pkg: Package,
|
|
||||||
entry: string
|
|
||||||
): Omit<webpack.Configuration, 'name'> & { name: string } {
|
|
||||||
const dev = process.env.NODE_ENV === 'development';
|
|
||||||
return {
|
|
||||||
name: entry,
|
|
||||||
context: ProjectRoot.value,
|
|
||||||
experiments: {
|
|
||||||
topLevelAwait: true,
|
|
||||||
outputModule: pkg.packageJson.type === 'module',
|
|
||||||
syncWebAssembly: true,
|
|
||||||
},
|
|
||||||
entry: { index: entry },
|
|
||||||
output: {
|
|
||||||
filename: `main.js`,
|
|
||||||
path: pkg.distPath.value,
|
|
||||||
clean: true,
|
|
||||||
globalObject: 'globalThis',
|
|
||||||
},
|
|
||||||
target: ['node', 'es2022'],
|
|
||||||
externals: (data, callback) => {
|
|
||||||
if (
|
|
||||||
data.request &&
|
|
||||||
// import ... from 'module'
|
|
||||||
/^[a-zA-Z@]/.test(data.request) &&
|
|
||||||
// not workspace deps
|
|
||||||
!pkg.deps.some(dep => data.request!.startsWith(dep.name))
|
|
||||||
) {
|
|
||||||
callback(null, true);
|
|
||||||
} else {
|
|
||||||
callback(null, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
externalsPresets: { node: true },
|
|
||||||
node: { __dirname: false, __filename: false },
|
|
||||||
mode: dev ? 'development' : 'production',
|
|
||||||
devtool: 'source-map',
|
|
||||||
resolve: {
|
|
||||||
symlinks: true,
|
|
||||||
extensionAlias: { '.js': ['.js', '.ts'], '.mjs': ['.mjs', '.mts'] },
|
|
||||||
extensions: ['.js', '.ts', '.tsx', '.node'],
|
|
||||||
alias: { yjs: ProjectRoot.join('node_modules', 'yjs').value },
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
parser: {
|
|
||||||
javascript: { url: false, importMeta: false, createRequire: false },
|
|
||||||
},
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
enforce: 'pre',
|
|
||||||
include: /@blocksuite/,
|
|
||||||
use: ['source-map-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.node$/,
|
|
||||||
loader: Path.dir(import.meta.url).join('node-loader.js').value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.tsx?$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
loader: 'swc-loader',
|
|
||||||
options: {
|
|
||||||
// https://swc.rs/docs/configuring-swc/
|
|
||||||
jsc: {
|
|
||||||
preserveAllComments: true,
|
|
||||||
parser: {
|
|
||||||
syntax: 'typescript',
|
|
||||||
dynamicImport: true,
|
|
||||||
topLevelAwait: true,
|
|
||||||
tsx: true,
|
|
||||||
decorators: true,
|
|
||||||
},
|
|
||||||
target: 'es2022',
|
|
||||||
externalHelpers: false,
|
|
||||||
transform: {
|
|
||||||
legacyDecorator: true,
|
|
||||||
decoratorMetadata: true,
|
|
||||||
react: { runtime: 'automatic' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sourceMaps: true,
|
|
||||||
inlineSourcesContent: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
plugins: compact([
|
|
||||||
new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
|
|
||||||
new webpack.IgnorePlugin({
|
|
||||||
checkResource(resource) {
|
|
||||||
const lazyImports = [
|
|
||||||
'@nestjs/microservices',
|
|
||||||
'@nestjs/websockets/socket-module',
|
|
||||||
'@apollo/subgraph',
|
|
||||||
'@apollo/gateway',
|
|
||||||
'@as-integrations/fastify',
|
|
||||||
'ts-morph',
|
|
||||||
'class-validator',
|
|
||||||
'class-transformer',
|
|
||||||
];
|
|
||||||
return lazyImports.some(lazyImport =>
|
|
||||||
resource.startsWith(lazyImport)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env.NODE_ENV': '"production"',
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
stats: { errorDetails: true },
|
|
||||||
optimization: {
|
|
||||||
nodeEnv: false,
|
|
||||||
minimize: !dev,
|
|
||||||
minimizer: [
|
|
||||||
new TerserPlugin({
|
|
||||||
minify: TerserPlugin.swcMinify,
|
|
||||||
parallel: true,
|
|
||||||
extractComments: true,
|
|
||||||
terserOptions: {
|
|
||||||
ecma: 2020,
|
|
||||||
compress: { unused: true },
|
|
||||||
mangle: { keep_classnames: true },
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
performance: { hints: false },
|
|
||||||
ignoreWarnings: [/^(?!CriticalDependenciesWarning$)/],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface BuildFlags {
|
|
||||||
mode: 'development' | 'production';
|
|
||||||
channel: 'stable' | 'beta' | 'canary' | 'internal';
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"types": ["build-config", "affine__env", "webpack-env"],
|
"types": ["build-config", "affine__env"],
|
||||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"composite": true
|
"composite": true
|
||||||
|
|||||||
Reference in New Issue
Block a user