Compare commits

...

7 commits

Author SHA1 Message Date
ScriptedAlchemy
51f0f6e5c3 home app fragment 2024-07-21 23:32:16 +08:00
ScriptedAlchemy
1b33835b14 home app fragment 2024-07-21 18:35:43 +08:00
hardfist
03eba8f996 chore: reduce modified code 2024-07-21 18:20:58 +08:00
hardfist
1fa178b627 chore: make next-css work 2024-07-21 18:07:01 +08:00
hardfist
127fccb133 chore: remove log 2024-07-21 17:16:41 +08:00
hardfist
849568cc14 chore: clean some code 2024-07-21 17:14:40 +08:00
hardfist
001664e3bc chore: add basic-export build work 2024-07-21 17:07:05 +08:00
38 changed files with 1910 additions and 190 deletions

View file

@ -1,8 +1,8 @@
{
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"dev": "RSPACK_CONFIG_VALIDATE=loose-silent next",
"build": "cross-env RSPACK_CONFIG_VALIDATE=loose-silent NEXT_TELEMETRY_DISABLED=1 node --trace-deprecation --enable-source-maps ../../packages/next/dist/bin/next build",
"start": "next start"
},
"dependencies": {

View file

@ -1,8 +1,8 @@
{
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"dev": "RSPACK_CONFIG_VALIDATE=loose-silent next",
"build": "cross-env RSPACK_CONFIG_VALIDATE=loose-silent NEXT_TELEMETRY_DISABLED=1 node --trace-deprecation --enable-source-maps ../../packages/next/dist/bin/next build",
"start": "serve out"
},
"dependencies": {

View file

@ -0,0 +1,77 @@
import React from "react";
import { Menu, Layout } from "antd";
import { useRouter } from "next/router";
import "./menu";
const SharedNav = () => {
const { asPath, push } = useRouter();
let activeMenu;
if (asPath === "/" || asPath.startsWith("/home")) {
activeMenu = "/";
} else if (asPath.startsWith("/shop")) {
activeMenu = "/shop";
} else if (asPath.startsWith("/checkout")) {
activeMenu = "/checkout";
}
const menuItems = [
{
className: "home-menu-link",
label: (
<>
Home <sup>3000</sup>
</>
),
key: "/",
onMouseEnter: () => {},
},
{
className: "shop-menu-link",
label: (
<>
Shop <sup>3001</sup>
</>
),
key: "/shop",
},
{
className: "checkout-menu-link",
label: (
<>
Checkout <sup>3002</sup>
</>
),
key: "/checkout",
},
];
return (
<Layout.Header>
<div className="header-logo">nextjs-mf</div>
<Menu
theme="dark"
mode="horizontal"
selectedKeys={activeMenu ? [activeMenu] : undefined}
onClick={({ key }) => {
push(key);
}}
items={menuItems}
/>
<style jsx>
{`
.header-logo {
float: left;
width: 200px;
height: 31px;
margin-right: 24px;
color: white;
font-size: 2rem;
}
`}
</style>
</Layout.Header>
);
};
export default SharedNav;

View file

@ -0,0 +1,37 @@
import type { ItemType } from "antd/es/menu/interface";
import { useRouter } from "next/router";
import { Menu } from "antd";
const menuItems: ItemType[] = [
{ label: "Main home", key: "/" },
{ label: "Test hook from remote", key: "/home/test-remote-hook" },
{ label: "Test broken remotes", key: "/home/test-broken-remotes" },
{ label: "Exposed pages", key: "/home/exposed-pages" },
{
label: "Exposed components",
type: "group",
children: [{ label: "home/SharedNav", key: "/home/test-shared-nav" }],
},
];
export default function AppMenu() {
const router = useRouter();
return (
<>
<div
style={{ padding: "10px", fontWeight: 600, backgroundColor: "#fff" }}
>
Home App Menu
</div>
<Menu
mode="inline"
selectedKeys={[router.asPath]}
style={{ height: "100%" }}
onClick={({ key }) => router.push(key)}
items={menuItems}
/>
</>
);
}

View file

@ -0,0 +1,3 @@
.tjhin {
display: flex;
}

View file

@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View file

@ -0,0 +1,13 @@
const nextConfig = {
webpack(config, options) {
config.plugins.push({
name: "xxx",
apply(compiler) {
compiler.options.devtool = false;
},
});
return config;
},
};
module.exports = nextConfig;

View file

@ -0,0 +1,29 @@
{
"name": "@module-federation/3000-home",
"version": "1.0.0",
"private": true,
"dependencies": {
"next": "latest",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"antd": "5.19.1",
"@ant-design/cssinjs": "^1.21.0",
"buffer": "5.7.1",
"encoding": "0.1.13",
"eslint-scope": "7.2.2",
"events": "3.3.0",
"js-cookie": "3.0.5",
"lodash": "4.17.21",
"node-fetch": "2.7.0",
"schema-utils": "3.3.0",
"terser-webpack-plugin": "5.3.10",
"typescript": "5.3.3",
"upath": "2.0.1",
"url": "0.11.3",
"util": "0.12.5"
},
"scripts": {
"dev": "RSPACK_CONFIG_VALIDATE=loose-silent next",
"build": "cross-env RSPACK_CONFIG_VALIDATE=loose-silent NEXT_TELEMETRY_DISABLED=1 node --trace-deprecation --enable-source-maps ../../packages/next/dist/bin/next build"
}
}

View file

@ -0,0 +1,70 @@
import * as React from "react";
import { useState } from "react";
import App from "next/app";
import { Layout, version, ConfigProvider } from "antd";
import { StyleProvider } from "@ant-design/cssinjs";
import Router, { useRouter } from "next/router";
const SharedNav = React.lazy(() => import("../components/SharedNav"));
import HostAppMenu from "../components/menu";
function MyApp(props) {
const { Component, pageProps } = props;
const { asPath } = useRouter();
const [MenuComponent, setMenuComponent] = useState(() => HostAppMenu);
const handleRouteChange = async (url) => {
if (url.startsWith("/shop")) {
} else if (url.startsWith("/checkout")) {
} else {
setMenuComponent(() => HostAppMenu);
}
};
// handle first route hit.
React.useEffect(() => {
handleRouteChange(asPath);
}, [asPath]);
//handle route change
React.useEffect(() => {
// Step 3: Subscribe on events
Router.events.on("routeChangeStart", handleRouteChange);
return () => {
Router.events.off("routeChangeStart", handleRouteChange);
};
}, []);
return (
<StyleProvider layer>
<ConfigProvider theme={{ hashed: false }}>
<Layout style={{ minHeight: "100vh" }} prefixCls={"dd"}>
<React.Suspense>
<SharedNav />
</React.Suspense>
<Layout>
<Layout.Sider width={200}>
<MenuComponent />
</Layout.Sider>
<Layout>
<Layout.Content style={{ background: "#fff", padding: 20 }}>
<Component {...pageProps} />
</Layout.Content>
<Layout.Footer
style={{
background: "#fff",
color: "#999",
textAlign: "center",
}}
>
antd@{version}
</Layout.Footer>
</Layout>
</Layout>
</Layout>
</ConfigProvider>
</StyleProvider>
);
}
MyApp.getInitialProps = async (ctx) => {
return App.getInitialProps(ctx);
};
export default MyApp;

View file

@ -0,0 +1,26 @@
import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
};
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;

View file

@ -0,0 +1,3 @@
export default function handler(req, res) {
res.status(200).json({ name: "John Doe" });
}

View file

@ -0,0 +1,19 @@
/* eslint-disable */
import { useState, useEffect } from "react";
export default function ExposedPages() {
const [pageMap] = useState("");
const [pageMapV2] = useState("");
return (
<>
<h1>This app exposes the following pages:</h1>
<h2>./pages-map</h2>
<pre>{JSON.stringify(pageMap, undefined, 2)}</pre>
<h2>./pages-map-v2</h2>
<pre>{JSON.stringify(pageMapV2, undefined, 2)}</pre>
</>
);
}

View file

@ -0,0 +1,22 @@
/* eslint-disable */
import Link from "next/link";
export default function TestBrokenRemotes() {
return (
<div>
<h2>This page is a test for broken remoteEntries.js</h2>
<p>
Check unresolved host {" "}
<Link href="/unresolved-host">/unresolved-host</Link> (on
http://localhost:<b>3333</b>/_next/static/chunks/remoteEntry.js)
</p>
<p>
Check wrong response for remoteEntry {" "}
<Link href="/wrong-entry">/wrong-entry</Link> (on
http://localhost:3000/_next/static/chunks/remoteEntry<b>Wrong</b>
.js)
</p>
</div>
);
}

View file

@ -0,0 +1,16 @@
import { NextPage } from "next";
const TestRemoteHook: NextPage = () => {
return (
<>
<div>
Page with custom remote hook. You must see text in red box below:
</div>
<div style={{ border: "1px solid red", padding: 5 }}>
blank text for now
</div>
</>
);
};
export default TestRemoteHook;

View file

@ -0,0 +1,9 @@
import SharedNav from "../../components/SharedNav";
export default function TestSharedNav() {
return (
<div>
<SharedNav />
</div>
);
}

View file

@ -0,0 +1,139 @@
/* eslint-disable */
import React from "react";
import Head from "next/head";
const Home = () => {
return (
<>
<Head>
<title>Home</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<h1 style={{ fontSize: "2em" }}>
This is SPA combined from 3 different nextjs applications.
</h1>
<p className="description">
They utilize omnidirectional routing and pages or components are able to
be federated between applications.
</p>
<p>You may open any application by clicking on the links below:</p>
<ul>
<li>
<a
href="#reloadPage"
onClick={() => (window.location.href = "http://localhost:3000")}
>
localhost:3000
</a>
{" "}
<b>home</b>
</li>
<li>
<a
href="#reloadPage"
onClick={() => (window.location.href = "http://localhost:3001")}
>
localhost:3001
</a>
{" "}
<b>shop</b>
</li>
<li>
<a
href="#reloadPage"
onClick={() => (window.location.href = "http://localhost:3002")}
>
localhost:3002
</a>
{" "}
<b>checkout</b>
</li>
</ul>
<h2 style={{ marginTop: "30px" }}>Federation test cases</h2>
<table border={1} cellPadding={5}>
<thead>
<tr>
<td></td>
<td>Test case</td>
<td>Expected</td>
<td>Actual</td>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>
Loading remote component (CheckoutTitle) from localhost:3002
<br />
<blockquote>
lazy(()=&gt;import(&apos;checkout/CheckoutTitle&apos;))
</blockquote>
</td>
<td>
<h3>This title came from checkout with hooks data!!!</h3>
</td>
<td>old</td>
</tr>
<tr>
<td></td>
<td>
Load federated component from checkout with old antd version
</td>
<td>[Button from antd@5.18.3]</td>
<td>test</td>
</tr>
<tr>
<td></td>
<td>
Loading remote component with PNG image from localhost:3001
<br />
<blockquote>(check publicPath fix in image-loader)</blockquote>
</td>
<td>
<img className="home-webpack-png" src="./webpack.png" />
</td>
<td>other thing</td>
</tr>
<tr>
<td></td>
<td>
Loading remote component with SVG from localhost:3001
<br />
<blockquote>(check publicPath fix in url-loader)</blockquote>
</td>
<td>
<img src="./webpack.svg" />
</td>
<td>anothaaaaaa</td>
</tr>
</tbody>
</table>
<h2 style={{ marginTop: "30px" }}>Other problems to fix:</h2>
<ul>
<li>
🐞 Incorrectly exposed modules in next.config.js (e.g. typo in path)
do not throw an error in console
</li>
<li>
📝 Try to introduce a remote entry loading according to prefix path.
It will be nice runtime improvement if you have eg 20 apps and load
just one remoteEntry instead of all of them.
</li>
<li>
📝 It will be nice to regenerate remoteEntry if new page was added in
remote app.
</li>
<li>
📝 Remote components do not regenerate chunks if they were changed.
</li>
</ul>
</>
);
};
Home.getInitialProps = () => {
console.log("home calls get initial props");
return {};
};
export default Home;

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,5 @@
<svg viewBox="0 0 3046.7 875.7" xmlns="http://www.w3.org/2000/svg">
<path d="m387 0 387 218.9v437.9l-387 218.9-387-218.9v-437.9z" fill="#fff"/>
<path d="m704.9 641.7-305.1 172.6v-134.4l190.1-104.6zm20.9-18.9v-360.9l-111.6 64.5v232zm-657.9 18.9 305.1 172.6v-134.4l-190.2-104.6zm-20.9-18.9v-360.9l111.6 64.5v232zm13.1-384.3 312.9-177v129.9l-200.5 110.3-1.6.9zm652.6 0-312.9-177v129.9l200.5 110.2 1.6.9z" fill="#8ed6fb"/>
<path d="m373 649.3-187.6-103.2v-204.3l187.6 108.3zm26.8 0 187.6-103.1v-204.4l-187.6 108.3zm-201.7-331.1 188.3-103.5 188.3 103.5-188.3 108.7z" fill="#1c78c0"/>
</svg>

After

Width:  |  Height:  |  Size: 592 B

View file

@ -0,0 +1,5 @@
declare module "shop/useCustomRemoteHook";
declare module "shop/WebpackSvg";
declare module "shop/WebpackPng";
declare module "checkout/CheckoutTitle";
declare module "checkout/ButtonOldAnt";

View file

@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "environment.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

View file

@ -1,5 +1,5 @@
import css from "./hello-world.module.css";
console.log('css:',css);
export default function HelloWorld() {
return (
<div className={css.hello}>

View file

@ -99,6 +99,7 @@
"caniuse-lite": "^1.0.30001579",
"graceful-fs": "^4.2.11",
"postcss": "8.4.31",
"source-map-support": "0.5.21",
"styled-jsx": "5.1.6"
},
"peerDependencies": {
@ -163,6 +164,7 @@
"@next/swc": "15.0.0-canary.56",
"@opentelemetry/api": "1.6.0",
"@playwright/test": "1.41.2",
"@rspack/core": "alpha",
"@swc/core": "1.6.6",
"@swc/types": "0.1.7",
"@taskr/clear": "1.1.0",

View file

@ -922,8 +922,9 @@ export default async function getBaseWebpackConfig(
context,
request,
dependencyType,
contextInfo.issuerLayer as WebpackLayerName,
contextInfo?.issuerLayer as WebpackLayerName,
(options) => {
return true as any;
const resolveFunction = getResolve(options)
return (resolveContext: string, requestToResolve: string) =>
new Promise((resolve, reject) => {
@ -1037,7 +1038,6 @@ export default async function getBaseWebpackConfig(
}): boolean {
return (
!module.type?.startsWith('css') &&
module.size() > 160000 &&
/node_modules[/\\]/.test(module.nameForCondition() || '')
)
},
@ -1104,35 +1104,35 @@ export default async function getBaseWebpackConfig(
const {
TerserPlugin,
} = require('./webpack/plugins/terser-webpack-plugin/src/index.js')
new TerserPlugin({
terserOptions: {
...terserOptions,
compress: {
...terserOptions.compress,
},
mangle: {
...terserOptions.mangle,
},
},
}).apply(compiler)
// new TerserPlugin({
// terserOptions: {
// ...terserOptions,
// compress: {
// ...terserOptions.compress,
// },
// mangle: {
// ...terserOptions.mangle,
// },
// },
// }).apply(compiler)
},
// Minify CSS
(compiler: webpack.Compiler) => {
const {
CssMinimizerPlugin,
} = require('./webpack/plugins/css-minimizer-plugin')
new CssMinimizerPlugin({
postcssOptions: {
map: {
// `inline: false` generates the source map in a separate file.
// Otherwise, the CSS file is needlessly large.
inline: false,
// `annotation: false` skips appending the `sourceMappingURL`
// to the end of the CSS file. Webpack already handles this.
annotation: false,
},
},
}).apply(compiler)
// new CssMinimizerPlugin({
// postcssOptions: {
// map: {
// // `inline: false` generates the source map in a separate file.
// // Otherwise, the CSS file is needlessly large.
// inline: false,
// // `annotation: false` skips appending the `sourceMappingURL`
// // to the end of the CSS file. Webpack already handles this.
// annotation: false,
// },
// },
// }).apply(compiler)
},
],
},
@ -1740,7 +1740,7 @@ export default async function getBaseWebpackConfig(
resource.request,
'.shared-runtime'
)
const layer = resource.contextInfo.issuerLayer
const layer = 'pages' as string
let runtime
switch (layer) {
@ -1757,7 +1757,7 @@ export default async function getBaseWebpackConfig(
}
),
dev && new MemoryWithGcCachePlugin({ maxGenerations: 5 }),
dev && isClient && new ReactRefreshWebpackPlugin(webpack),
// dev && isClient && new ReactRefreshWebpackPlugin(webpack),
// Makes sure `Buffer` and `process` are polyfilled in client and flight bundles (same behavior as webpack 4)
(isClient || isEdgeServer) &&
new webpack.ProvidePlugin({
@ -1788,7 +1788,7 @@ export default async function getBaseWebpackConfig(
runtimeAsset: `server/${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js`,
dev,
}),
(isClient || isEdgeServer) && new DropClientPage(),
// (isClient || isEdgeServer) && new DropClientPage(),
isNodeServer &&
!dev &&
new (require('./webpack/plugins/next-trace-entrypoints-plugin')
@ -1823,9 +1823,9 @@ export default async function getBaseWebpackConfig(
const { NextJsRequireCacheHotReloader } =
require('./webpack/plugins/nextjs-require-cache-hot-reloader') as typeof import('./webpack/plugins/nextjs-require-cache-hot-reloader')
const devPlugins: any[] = [
new NextJsRequireCacheHotReloader({
serverComponents: hasAppDir,
}),
// new NextJsRequireCacheHotReloader({
// serverComponents: hasAppDir,
// }),
]
if (isClient || isEdgeServer) {
@ -1876,11 +1876,11 @@ export default async function getBaseWebpackConfig(
require('./webpack/plugins/font-stylesheet-gathering-plugin') as {
FontStylesheetGatheringPlugin: typeof import('./webpack/plugins/font-stylesheet-gathering-plugin').FontStylesheetGatheringPlugin
}
return new FontStylesheetGatheringPlugin({
adjustFontFallbacks: config.experimental.adjustFontFallbacks,
adjustFontFallbacksWithSizeAdjust:
config.experimental.adjustFontFallbacksWithSizeAdjust,
})
// return new FontStylesheetGatheringPlugin({
// adjustFontFallbacks: config.experimental.adjustFontFallbacks,
// adjustFontFallbacksWithSizeAdjust:
// config.experimental.adjustFontFallbacksWithSizeAdjust,
// })
})(),
new WellKnownErrorsPlugin(),
isClient &&
@ -1929,9 +1929,9 @@ export default async function getBaseWebpackConfig(
new NextFontManifestPlugin({
appDir,
}),
!dev &&
isClient &&
new CssChunkingPlugin(config.experimental.cssChunking === 'strict'),
// !dev &&
// isClient &&
// new CssChunkingPlugin(config.experimental.cssChunking === 'strict'),
!dev &&
isClient &&
new (require('./webpack/plugins/telemetry-plugin').TelemetryPlugin)(
@ -2266,22 +2266,22 @@ export default async function getBaseWebpackConfig(
const webpack5Config = webpackConfig as webpack.Configuration
// disable lazy compilation of entries as next.js has it's own method here
if (webpack5Config.experiments?.lazyCompilation === true) {
webpack5Config.experiments.lazyCompilation = {
entries: false,
}
} else if (
typeof webpack5Config.experiments?.lazyCompilation === 'object' &&
webpack5Config.experiments.lazyCompilation.entries !== false
) {
webpack5Config.experiments.lazyCompilation.entries = false
}
// if (webpack5Config.experiments?.lazyCompilation === true) {
// webpack5Config.experiments.lazyCompilation = {
// entries: false,
// }
// } else if (
// typeof webpack5Config.experiments?.lazyCompilation === 'object' &&
// webpack5Config.experiments.lazyCompilation.entries !== false
// ) {
// webpack5Config.experiments.lazyCompilation.entries = false
// }
if (typeof (webpackConfig as any).then === 'function') {
console.warn(
'> Promise returned in next config. https://nextjs.org/docs/messages/promise-in-next-config'
)
}
// if (typeof (webpackConfig as any).then === 'function') {
// console.warn(
// '> Promise returned in next config. https://nextjs.org/docs/messages/promise-in-next-config'
// )
// }
}
const rules = webpackConfig.module?.rules || []

View file

@ -591,7 +591,7 @@ export const css = curry(async function css(
if (ctx.isClient && (ctx.isProduction || ctx.hasAppDir)) {
// Extract CSS as CSS file(s) in the client-side production bundle.
const MiniCssExtractPlugin =
require('../../../plugins/mini-css-extract-plugin').default
require('@rspack/core').CssExtractRspackPlugin;
fns.push(
plugin(
// @ts-ignore webpack 5 compat

View file

@ -33,7 +33,7 @@ export function isCSSMod(mod: {
mod.loaders?.some(
({ loader }) =>
loader.includes('next-style-loader/index.js') ||
loader.includes('mini-css-extract-plugin/loader.js') ||
loader.includes('rspack.CssExtractRspackPlugin.loader') ||
loader.includes('@vanilla-extract/webpack-plugin/loader/')
)
)

View file

@ -568,7 +568,7 @@ function getExtractMetadata(params: {
metadataByEntry.clear()
const telemetry: Telemetry | undefined = traceGlobals.get('telemetry')
for (const [entryName, entry] of compilation.entries) {
for (const [entryName, entry] of compilation.entries ?? []) {
if (entry.options.runtime !== EDGE_RUNTIME_WEBPACK) {
// Only process edge runtime entries
continue
@ -782,9 +782,9 @@ export default class MiddlewarePlugin {
compiler,
compilation,
})
hooks.parser.for('javascript/auto').tap(NAME, codeAnalyzer)
hooks.parser.for('javascript/dynamic').tap(NAME, codeAnalyzer)
hooks.parser.for('javascript/esm').tap(NAME, codeAnalyzer)
// hooks.parser.for('javascript/auto').tap(NAME, codeAnalyzer)
// hooks.parser.for('javascript/dynamic').tap(NAME, codeAnalyzer)
// hooks.parser.for('javascript/esm').tap(NAME, codeAnalyzer)
/**
* Extract all metadata for the entry points in a Map object.

View file

@ -677,6 +677,7 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance {
}
apply(compiler: webpack.Compiler) {
return;
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
const readlink = async (path: string): Promise<string | null> => {
try {

View file

@ -63,7 +63,7 @@ export class ProfilingPlugin {
} = {}
) {
let span: Span | undefined
startHook.tap(
startHook?.tap(
{ name: pluginName, stage: -Infinity },
(...params: any[]) => {
const name = typeof spanName === 'function' ? spanName() : spanName
@ -75,7 +75,7 @@ export class ProfilingPlugin {
if (onStart) onStart(span, ...params)
}
)
stopHook.tap({ name: pluginName, stage: Infinity }, (...params: any[]) => {
stopHook?.tap({ name: pluginName, stage: Infinity }, (...params: any[]) => {
// `stopHook` may be triggered when `startHook` has not in cases
// where `stopHook` is used as the terminating event for more
// than one pair of hooks.
@ -149,54 +149,54 @@ export class ProfilingPlugin {
compiler.hooks.compilation.tap(
{ name: pluginName, stage: -Infinity },
(compilation: any) => {
compilation.hooks.buildModule.tap(pluginName, (module: any) => {
const moduleType = (() => {
const r = module.userRequest
if (!r || r.endsWith('!')) {
return ''
} else {
const resource = r.split('!').pop()
const match = /^[^?]+\.([^?]+)$/.exec(resource)
return match ? match[1] : ''
}
})()
// compilation.hooks.buildModule.tap(pluginName, (module: any) => {
// const moduleType = (() => {
// const r = module.userRequest
// if (!r || r.endsWith('!')) {
// return ''
// } else {
// const resource = r.split('!').pop()
// const match = /^[^?]+\.([^?]+)$/.exec(resource)
// return match ? match[1] : ''
// }
// })()
const issuerModule = compilation?.moduleGraph?.getIssuer(module)
// const issuerModule = compilation?.moduleGraph?.getIssuer(module)
let span: Span
// let span: Span
const moduleSpans = moduleSpansByCompilation.get(compilation)
const spanName = `build-module${moduleType ? `-${moduleType}` : ''}`
const issuerSpan: Span | undefined =
issuerModule && moduleSpans?.get(issuerModule)
if (issuerSpan) {
span = issuerSpan.traceChild(spanName)
} else {
let parentSpan: Span | undefined
for (const incomingConnection of compilation.moduleGraph.getIncomingConnections(
module
)) {
const entrySpan = spans.get(incomingConnection.dependency)
if (entrySpan) {
parentSpan = entrySpan
break
}
}
// const moduleSpans = moduleSpansByCompilation.get(compilation)
// const spanName = `build-module${moduleType ? `-${moduleType}` : ''}`
// const issuerSpan: Span | undefined =
// issuerModule && moduleSpans?.get(issuerModule)
// if (issuerSpan) {
// span = issuerSpan.traceChild(spanName)
// } else {
// let parentSpan: Span | undefined
// for (const incomingConnection of compilation.moduleGraph?.getIncomingConnections(
// module
// )) {
// const entrySpan = spans.get(incomingConnection.dependency)
// if (entrySpan) {
// parentSpan = entrySpan
// break
// }
// }
if (!parentSpan) {
const compilationSpan = spans.get(compilation)
if (!compilationSpan) {
return
}
// if (!parentSpan) {
// const compilationSpan = spans.get(compilation)
// if (!compilationSpan) {
// return
// }
parentSpan = compilationSpan
}
span = parentSpan.traceChild(spanName)
}
span.setAttribute('name', module.userRequest)
span.setAttribute('layer', module.layer)
moduleSpans!.set(module, span)
})
// parentSpan = compilationSpan
// }
// span = parentSpan.traceChild(spanName)
// }
// span.setAttribute('name', module.userRequest)
// span.setAttribute('layer', module.layer)
// moduleSpans!.set(module, span)
// })
const moduleHooks = NormalModule.getCompilationHooks(compilation)
moduleHooks.readResource.for(undefined).intercept({
@ -214,17 +214,41 @@ export class ProfilingPlugin {
moduleHooks.loader.tap(
pluginName,
(loaderContext: any, module: any) => {
const moduleSpan = moduleSpansByCompilation
.get(compilation)
?.get(module)
// const moduleSpan = moduleSpansByCompilation
// .get(compilation)
// ?.get(module)
const moduleSpan = {
traceChild() {
return {
traceFn(fn: any) {
return fn();
},
traceAsyncFn(fn:any){
return fn();
},
setAttribute() {},
traceChild(){
return {
traceFn(fn: any) {
return fn();
},
traceAsyncFn(fn:any){
return fn();
},
setAttribute() {},
}
}
}
},
}
loaderContext.currentTraceSpan = moduleSpan
}
)
compilation.hooks.succeedModule.tap(pluginName, (module: any) => {
compilation.hooks.succeedModule?.tap(pluginName, (module: any) => {
moduleSpansByCompilation?.get(compilation)?.get(module)?.stop()
})
compilation.hooks.failedModule.tap(pluginName, (module: any) => {
compilation.hooks.failedModule?.tap(pluginName, (module: any) => {
moduleSpansByCompilation?.get(compilation)?.get(module)?.stop()
})
@ -243,7 +267,7 @@ export class ProfilingPlugin {
}
)
compilation.hooks.addEntry.tap(pluginName, (entry: any) => {
compilation.hooks.addEntry?.tap(pluginName, (entry: any) => {
const parentSpan =
makeSpanByCompilation.get(compilation) || spans.get(compilation)
if (!parentSpan) {
@ -254,11 +278,11 @@ export class ProfilingPlugin {
spans.set(entry, addEntrySpan)
})
compilation.hooks.succeedEntry.tap(pluginName, (entry: any) => {
compilation.hooks.succeedEntry?.tap(pluginName, (entry: any) => {
spans.get(entry)?.stop()
spans.delete(entry)
})
compilation.hooks.failedEntry.tap(pluginName, (entry: any) => {
compilation.hooks.failedEntry?.tap(pluginName, (entry: any) => {
spans.get(entry)?.stop()
spans.delete(entry)
})
@ -355,31 +379,31 @@ export class ProfilingPlugin {
)
const logs = new Map()
const originalTime = compilation.logger.time
const originalTimeEnd = compilation.logger.timeEnd
const originalTime = compilation.logger?.time
const originalTimeEnd = compilation.logger?.timeEnd
compilation.logger.time = (label: string) => {
if (!inTraceLabelsSeal(label)) {
return originalTime.call(compilation.logger, label)
}
const span = sealSpanByCompilation.get(compilation)
if (span) {
logs.set(label, span.traceChild(label.replace(/ /g, '-')))
}
return originalTime.call(compilation.logger, label)
}
compilation.logger.timeEnd = (label: string) => {
if (!inTraceLabelsSeal(label)) {
return originalTimeEnd.call(compilation.logger, label)
}
// compilation.logger.time = (label: string) => {
// if (!inTraceLabelsSeal(label)) {
// return originalTime.call(compilation.logger, label)
// }
// const span = sealSpanByCompilation.get(compilation)
// if (span) {
// logs.set(label, span.traceChild(label.replace(/ /g, '-')))
// }
// return originalTime.call(compilation.logger, label)
// }
// compilation.logger.timeEnd = (label: string) => {
// if (!inTraceLabelsSeal(label)) {
// return originalTimeEnd.call(compilation.logger, label)
// }
const span = logs.get(label)
if (span) {
span.stop()
logs.delete(label)
}
return originalTimeEnd.call(compilation.logger, label)
}
// const span = logs.get(label)
// if (span) {
// span.stop()
// logs.delete(label)
// }
// return originalTimeEnd.call(compilation.logger, label)
// }
}
)
}

View file

@ -134,9 +134,9 @@ function buildManifest(
}
}
}
for (const module of compilation.modules) {
module.blocks.forEach(handleBlock)
}
// for (const module of compilation.modules) {
// module.blocks.forEach(handleBlock)
// }
manifest = Object.keys(manifest)
.sort()

View file

@ -1,4 +1,5 @@
#!/usr/bin/env node
require('source-map-support').install();
import '../server/lib/cpu-profile'
import { existsSync } from 'fs'

View file

@ -1,4 +1,5 @@
#!/usr/bin/env node
require('source-map-support').install();
import '../server/lib/cpu-profile'
import type { StartServerOptions } from '../server/lib/start-server'

View file

@ -21,6 +21,7 @@ exports.init = function () {
webpack: require('webpack'),
})
} else {
Object.assign(exports, require('./bundle5')())
console.log('load rspack');
Object.assign(exports, require('@rspack/core'))
}
}

View file

@ -791,7 +791,7 @@ export default class NextNodeServer extends BaseServer<
}
protected getFontManifest(): FontManifest {
return requireFontManifest(this.distDir)
return requireFontManifest(this.distDir) as any;
}
protected getNextFontManifest(): NextFontManifest | undefined {

View file

@ -133,6 +133,7 @@ export async function requirePage(
export function requireFontManifest(distDir: string) {
const serverBuildPath = path.join(distDir, SERVER_DIRECTORY)
return {} as FontManifest;
const fontManifest = loadManifest(
path.join(serverBuildPath, AUTOMATIC_FONT_OPTIMIZATION_MANIFEST)
) as FontManifest

File diff suppressed because it is too large Load diff

View file

@ -2,3 +2,5 @@ packages:
- 'packages/*'
- 'bench/*'
- 'packages/next-swc/crates/next-core/js'
- 'examples/next-css'
- 'examples/federation-single-app'