@wular/pnext 0.0.3 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/bin/pnext +1 -1
- package/config/lint/base.js +7 -7
- package/config/ts/base.json +2 -4
- package/config/ts/react.json +2 -6
- package/package.json +23 -2
- package/reference/compat.md +1 -1
- package/reference/config.md +2 -2
- package/reference/css.md +13 -9
- package/reference/dev.md +1 -1
- package/reference/metadata.md +7 -7
- package/reference/navigation.md +35 -28
- package/reference/performance.md +70 -70
- package/reference/rendering.md +17 -17
- package/reference/routing.md +17 -17
- package/reference/typegen.md +12 -8
- package/src/api/cache.ts +36 -37
- package/src/api/client-cache.ts +2 -2
- package/src/api/client-navigation.ts +113 -109
- package/src/api/dynamic.tsx +58 -55
- package/src/api/link.tsx +49 -52
- package/src/api/navigation.ts +59 -58
- package/src/api/server.ts +152 -144
- package/src/api/suspense.ts +4 -4
- package/src/cli/adapters/vercel-warm.ts +126 -121
- package/src/cli/adapters/vercel.ts +437 -443
- package/src/cli/analyze.ts +333 -144
- package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
- package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
- package/src/cli/build.ts +976 -978
- package/src/cli/create.ts +71 -63
- package/src/cli/dev.ts +116 -116
- package/src/cli/index.ts +88 -85
- package/src/cli/migrate/package-json.ts +73 -71
- package/src/cli/migrate/report.ts +32 -33
- package/src/cli/migrate/{index.ts → run.ts} +48 -49
- package/src/cli/migrate/scan.ts +46 -46
- package/src/cli/migrate/spinner.ts +9 -9
- package/src/cli/migrate/tsconfig.ts +35 -35
- package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
- package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
- package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
- package/src/cli/start.ts +65 -66
- package/src/{typegen.ts → cli/typegen.ts} +59 -59
- package/src/client/build.ts +794 -768
- package/src/client/chunk-fold.ts +245 -240
- package/src/client/{paths.ts → chunk-name.ts} +6 -6
- package/src/client/entry.ts +162 -147
- package/src/client/prebuilt.ts +231 -223
- package/src/client/profile.ts +29 -29
- package/src/client/react-compiler.ts +20 -15
- package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
- package/src/client/reference-stub.ts +51 -51
- package/src/client/reference.ts +19 -19
- package/src/{api → client}/router/events.ts +17 -17
- package/src/{api → client}/router/history.ts +16 -16
- package/src/{api → client}/router/hub.ts +52 -53
- package/src/{api/router.ts → client/router/index.ts} +61 -60
- package/src/{api → client}/router/policies.ts +24 -24
- package/src/{api → client}/router/runtime.ts +1988 -1961
- package/src/{api → client}/router/types.ts +93 -98
- package/src/compat/actions/client-plugin.ts +42 -43
- package/src/compat/actions/client-stub.ts +14 -14
- package/src/compat/actions/{action-client.ts → client.ts} +194 -193
- package/src/compat/actions/config.ts +63 -64
- package/src/compat/actions/detect.ts +68 -68
- package/src/compat/actions/discovery.ts +105 -105
- package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
- package/src/compat/actions/early-submit.ts +1 -1
- package/src/compat/actions/endpoint.ts +198 -198
- package/src/compat/actions/extensions.ts +811 -0
- package/src/compat/actions/flight.ts +23 -23
- package/src/compat/actions/form-state.ts +34 -34
- package/src/compat/actions/hoist.ts +382 -236
- package/src/compat/actions/ids.ts +7 -12
- package/src/compat/actions/index.ts +8 -8
- package/src/compat/actions/instances.ts +46 -46
- package/src/compat/actions/origin.ts +47 -48
- package/src/compat/actions/protocol.ts +22 -22
- package/src/compat/actions/registry.ts +19 -19
- package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
- package/src/compat/actions/rewrite.ts +125 -125
- package/src/compat/actions/{action-router.ts → router.ts} +10 -10
- package/src/compat/actions/serve.ts +132 -136
- package/src/compat/actions/server-tag.ts +4 -4
- package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
- package/src/compat/actions/unrecognized-error.ts +4 -4
- package/src/compat/{index.ts → aliases.ts} +112 -109
- package/src/compat/bundler/bun-externals.ts +18 -18
- package/src/compat/bundler/cjs-exports.ts +271 -223
- package/src/compat/bundler/config.ts +116 -111
- package/src/compat/bundler/externals.ts +12 -12
- package/src/compat/bundler/import-meta-url.ts +19 -19
- package/src/compat/bundler/modularize-imports.ts +36 -33
- package/src/compat/bundler/new-url-asset.ts +22 -24
- package/src/compat/bundler/optimize-package-imports.ts +111 -107
- package/src/compat/bundler/polyfill.ts +28 -28
- package/src/compat/bundler/react-compiler.ts +35 -29
- package/src/compat/bundler/react-profiler.tsx +11 -11
- package/src/compat/bundler/relay-transform.ts +48 -47
- package/src/compat/bundler/require-context.ts +119 -113
- package/src/compat/bundler/resolve-extensions.ts +19 -19
- package/src/compat/bundler/source-cache.ts +25 -25
- package/src/compat/bundler/static-imports.ts +7 -7
- package/src/compat/bundler/symlink-imports.ts +46 -46
- package/src/compat/bundler/tsconfig-paths.ts +13 -15
- package/src/compat/bundler/wasm.ts +58 -60
- package/src/compat/bundler/webpack-loaders.ts +254 -241
- package/src/compat/bundler/worker.ts +101 -104
- package/src/compat/cache/build-flags.ts +29 -29
- package/src/compat/cache/build-prerender-errors.ts +40 -44
- package/src/compat/cache/custom-handler.ts +60 -53
- package/src/compat/cache/fetch-patch.ts +240 -240
- package/src/compat/cache/handler.ts +27 -31
- package/src/compat/cache/modern-handler.ts +148 -126
- package/src/compat/cache/resume-data-cache.ts +47 -45
- package/src/compat/cache/revalidate.ts +233 -232
- package/src/compat/cache/runtime-error.ts +35 -35
- package/src/compat/cache/use-cache-transform.ts +442 -417
- package/src/compat/cache/use-cache.ts +650 -614
- package/src/compat/cache-control.ts +140 -142
- package/src/compat/client/base-path.ts +21 -20
- package/src/compat/client/css-order.ts +18 -18
- package/src/compat/client/errors/bare-boundary.ts +11 -11
- package/src/compat/client/errors/control-flow.ts +23 -23
- package/src/compat/client/errors/error-boundary.ts +61 -61
- package/src/compat/client/errors/global-error.ts +101 -91
- package/src/compat/client/errors/install.ts +71 -72
- package/src/compat/client/errors/lazy.ts +23 -23
- package/src/compat/client/errors/primitive-throw.ts +47 -45
- package/src/compat/client/errors/soft-refresh.ts +4 -4
- package/src/compat/client/link-status.ts +33 -33
- package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
- package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
- package/src/compat/client/navigation-scroll.ts +63 -63
- package/src/compat/client/optimistic-routing.ts +93 -88
- package/src/compat/client/prefetch-cache.ts +23 -24
- package/src/compat/client/route-announcer.ts +35 -35
- package/src/compat/client/segment-cache-policy.ts +20 -20
- package/src/compat/client/segment-cache.ts +309 -315
- package/src/compat/client/segment-prefetch.ts +127 -132
- package/src/compat/client/trailing-slash.ts +5 -4
- package/src/compat/css/chunking.ts +113 -116
- package/src/compat/css/inline-css.ts +21 -21
- package/src/compat/css/lightningcss.ts +37 -38
- package/src/compat/css/modules.ts +161 -175
- package/src/compat/css/nonce.ts +7 -7
- package/src/compat/css/sass-plugin.ts +18 -21
- package/src/compat/css/sass.ts +150 -152
- package/src/compat/css/styled-jsx-runtime.ts +27 -27
- package/src/compat/css/styled-jsx.ts +21 -21
- package/src/compat/edge-runtime.ts +27 -27
- package/src/compat/{adapter → export}/build-complete.ts +72 -75
- package/src/compat/export/client.ts +29 -31
- package/src/compat/export/{index.ts → emit.ts} +111 -110
- package/src/compat/export/standalone.ts +62 -54
- package/src/compat/image-optimizer/cache.ts +51 -49
- package/src/compat/image-optimizer/detect.ts +52 -52
- package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
- package/src/compat/image-optimizer/source.ts +77 -80
- package/src/compat/lifecycle/after-scope.ts +26 -26
- package/src/compat/lifecycle/after.ts +48 -45
- package/src/compat/lifecycle/error-funnel.ts +98 -102
- package/src/compat/lifecycle/error-serialize.ts +30 -26
- package/src/compat/lifecycle/error-ui.ts +67 -32
- package/src/compat/lifecycle/instrumentation-client.ts +36 -38
- package/src/compat/lifecycle/instrumentation.ts +85 -85
- package/src/compat/lifecycle/node-console.ts +11 -11
- package/src/compat/lifecycle/testmode.ts +160 -132
- package/src/compat/mdx/compile.ts +60 -57
- package/src/compat/mdx/plugin.ts +11 -11
- package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
- package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
- package/src/compat/metadata.ts +75 -81
- package/src/compat/next/cache.ts +68 -69
- package/src/compat/next/canonical-url.ts +9 -9
- package/src/compat/next/client-cache.ts +19 -19
- package/src/compat/next/client-navigation.ts +112 -116
- package/src/compat/next/client-only.ts +1 -1
- package/src/compat/next/client-script.tsx +99 -93
- package/src/compat/next/client-server.ts +10 -10
- package/src/compat/next/config-loader.ts +176 -173
- package/src/compat/next/config.ts +7 -7
- package/src/compat/next/constants.cjs +6 -6
- package/src/compat/next/constants.ts +6 -6
- package/src/compat/next/custom-server.ts +26 -24
- package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
- package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
- package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
- package/src/compat/next/dynamic.tsx +21 -18
- package/src/compat/next/error.tsx +52 -52
- package/src/compat/next/font/cache.ts +74 -74
- package/src/compat/next/font/google.ts +2 -2
- package/src/compat/next/font/index.ts +1 -1
- package/src/compat/next/font/local.ts +3 -3
- package/src/compat/next/font/runtime-client.ts +17 -15
- package/src/compat/next/font/runtime.ts +443 -408
- package/src/compat/next/font/shared.ts +120 -108
- package/src/compat/next/form.tsx +63 -63
- package/src/compat/next/head.tsx +2 -2
- package/src/compat/next/headers.ts +103 -95
- package/src/compat/next/image/client.tsx +220 -0
- package/src/compat/next/image/config.ts +56 -58
- package/src/compat/next/image/optimizer.ts +40 -36
- package/src/compat/next/image/patterns.ts +37 -40
- package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
- package/src/compat/next/image/shared.ts +65 -57
- package/src/compat/next/image/static-metadata.ts +98 -107
- package/src/compat/next/image/validate.ts +79 -88
- package/src/compat/next/image.tsx +19 -23
- package/src/compat/next/index.ts +1 -1
- package/src/compat/next/legacy-image.tsx +59 -60
- package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
- package/src/compat/next/link.tsx +158 -158
- package/src/compat/next/navigation.cjs +12 -3
- package/src/compat/next/navigation.ts +48 -50
- package/src/compat/next/offline.ts +27 -27
- package/src/compat/next/og.ts +121 -124
- package/src/compat/next/preferred-region.ts +13 -14
- package/src/compat/next/redirects.ts +58 -56
- package/src/compat/next/resource-hints.ts +73 -76
- package/src/compat/next/rewrites.ts +130 -133
- package/src/compat/next/root-params.ts +45 -45
- package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
- package/src/compat/next/router.cjs +4 -2
- package/src/compat/next/router.ts +58 -61
- package/src/compat/next/script.tsx +108 -108
- package/src/compat/next/server-only.ts +1 -1
- package/src/compat/next/server.ts +19 -19
- package/src/compat/next/svgr.ts +18 -17
- package/src/compat/next/telemetry.ts +24 -24
- package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
- package/src/compat/next/user-agent.ts +53 -49
- package/src/compat/next/web-vitals.ts +22 -24
- package/src/compat/otel/api.ts +41 -41
- package/src/compat/otel/client-trace-metadata.ts +25 -27
- package/src/compat/otel/fetch-span.ts +29 -29
- package/src/compat/otel/tracer.ts +331 -331
- package/src/compat/pages/api.ts +456 -0
- package/src/compat/pages/client-plugin.ts +36 -36
- package/src/compat/pages/router-state.ts +34 -34
- package/src/compat/pages/{index.ts → router.ts} +130 -135
- package/src/compat/ppr/io.ts +12 -12
- package/src/compat/ppr/missing-root-params.ts +34 -38
- package/src/compat/ppr/root-params-scan.ts +66 -66
- package/src/compat/ppr/root-params-transform.ts +24 -26
- package/src/compat/ppr/root-params.ts +30 -30
- package/src/compat/ppr/segment-config-incompat.ts +6 -7
- package/src/compat/protocol.ts +71 -70
- package/src/compat/react/action-state.ts +47 -48
- package/src/compat/react/client-lite.ts +15 -15
- package/src/compat/react/client.ts +4 -4
- package/src/compat/react/compiler-runtime.ts +11 -11
- package/src/compat/react/dom-client.ts +44 -44
- package/src/compat/react/dom-react-server.ts +10 -16
- package/src/compat/react/dom-server.ts +10 -10
- package/src/compat/react/dom.ts +52 -52
- package/src/compat/react/hooks-extra.ts +34 -35
- package/src/compat/react/parity.ts +64 -61
- package/src/compat/react/preact.ts +81 -82
- package/src/compat/react/react-server.ts +28 -28
- package/src/compat/react/router-shim.ts +1 -1
- package/src/compat/react/server-component-use.ts +8 -8
- package/src/compat/react/server-inserted-html.ts +30 -31
- package/src/compat/react/server.ts +53 -55
- package/src/compat/react/use.ts +32 -32
- package/src/compat/react/view-transition.ts +20 -20
- package/src/compat/register/actions.ts +35 -824
- package/src/compat/register/boot.ts +41 -41
- package/src/compat/register/build-tier.ts +5 -5
- package/src/compat/register/build.ts +74 -70
- package/src/compat/register/bundler.ts +161 -156
- package/src/compat/register/cache.ts +20 -20
- package/src/compat/register/client-errors.ts +3 -3
- package/src/compat/register/config.ts +6 -6
- package/src/compat/register/css-extras.ts +30 -34
- package/src/compat/register/edge-runtime.ts +3 -3
- package/src/compat/register/errors.ts +10 -12
- package/src/compat/register/export.ts +16 -16
- package/src/compat/register/font.ts +11 -11
- package/src/compat/register/hooks.ts +2 -2
- package/src/compat/register/image.ts +40 -40
- package/src/compat/register/index.ts +59 -62
- package/src/compat/register/instrumentation-client.ts +10 -10
- package/src/compat/register/lifecycle.ts +25 -28
- package/src/compat/register/mdx.ts +10 -10
- package/src/compat/register/middleware.ts +226 -16
- package/src/compat/register/otel.ts +80 -88
- package/src/compat/register/pages-api.ts +10 -463
- package/src/compat/register/ppr.ts +16 -16
- package/src/compat/register/protocol.ts +17 -18
- package/src/compat/register/proxy.ts +49 -51
- package/src/compat/register/render.ts +79 -76
- package/src/compat/register/routing.ts +162 -159
- package/src/compat/register/segment.ts +24 -1887
- package/src/compat/register/static-image.ts +3 -3
- package/src/compat/register/{misc.ts → taint.ts} +9 -9
- package/src/compat/register/typed-routes.ts +14 -14
- package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
- package/src/compat/register/validation.ts +18 -18
- package/src/compat/segment/loading-boundary.ts +43 -45
- package/src/compat/segment/page-slot.ts +69 -69
- package/src/compat/segment/serve.ts +1884 -0
- package/src/compat/segment/tree.ts +113 -112
- package/src/compat/segment/vary-key.ts +38 -38
- package/src/compat/segment/vary-params.ts +138 -142
- package/src/compat/static-params.ts +14 -12
- package/src/compat/tsconfig-defaults.ts +87 -91
- package/src/compat/typecheck/{index.ts → check.ts} +234 -212
- package/src/compat/typecheck/worker.ts +15 -12
- package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
- package/src/compat/typed-routes/manifest.ts +174 -170
- package/src/compat/typed-routes/typegen.ts +127 -110
- package/src/compat/validation/errors.ts +16 -19
- package/src/compat/validation/prerender-diagnostics.ts +521 -504
- package/src/compat/validation/{index.ts → validate.ts} +647 -648
- package/src/compat-bootstrap.ts +16 -16
- package/src/config.ts +69 -69
- package/src/css/build.ts +230 -227
- package/src/css/postcss.ts +79 -80
- package/src/css/worker.ts +14 -15
- package/src/dev/client-actions.ts +10 -10
- package/src/dev/client-chunk-store.ts +27 -27
- package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
- package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
- package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
- package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
- package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
- package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
- package/src/dev/server.ts +804 -820
- package/src/env.ts +46 -43
- package/src/extensions.ts +491 -478
- package/src/index.ts +8 -8
- package/src/internal.ts +20 -23
- package/src/{islands → render}/boundary-error.ts +3 -3
- package/src/render/hooks.ts +71 -71
- package/src/render/island-context.ts +14 -14
- package/src/render/metadata.ts +310 -310
- package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
- package/src/{ppr.ts → render/ppr.ts} +244 -245
- package/src/render/renderer.ts +2076 -2082
- package/src/render/resource-hints.ts +16 -17
- package/src/render/slots.tsx +224 -235
- package/src/{islands → render}/static-children.ts +9 -12
- package/src/{islands → render}/static-slots.ts +37 -37
- package/src/{cache/context.ts → request/cache.ts} +20 -20
- package/src/request/context.ts +107 -107
- package/src/{dynamic/source.ts → resolve/dynamic.ts} +152 -143
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +442 -186
- package/src/resolve/source-text.ts +37 -37
- package/src/{dynamic → resolve}/tree-shake.ts +132 -128
- package/src/routing/forwarded.ts +19 -19
- package/src/routing/handler.ts +84 -91
- package/src/routing/href.ts +69 -70
- package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
- package/src/{proxy.ts → routing/proxy.ts} +306 -312
- package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
- package/src/routing/routes.ts +833 -848
- package/src/routing/slots.ts +164 -160
- package/src/runtime/loader.ts +952 -0
- package/src/{dev → runtime}/module-cache.ts +309 -287
- package/src/{dev → runtime}/module-generations.ts +9 -9
- package/src/{dev → runtime}/module-transform.ts +81 -72
- package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
- package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
- package/src/runtime/vendor.ts +425 -404
- package/src/styles.d.ts +9 -0
- package/src/types.ts +320 -335
- package/src/utils/ansi.ts +5 -5
- package/src/utils/{source.ts → code.ts} +15 -12
- package/src/utils/content-type.ts +3 -3
- package/src/utils/decode.ts +2 -2
- package/src/utils/dev-profile.ts +13 -13
- package/src/utils/error-log.ts +6 -6
- package/src/utils/esbuild.ts +18 -18
- package/src/utils/fs-cache.ts +13 -13
- package/src/utils/fs.ts +57 -49
- package/src/utils/html.ts +20 -24
- package/src/utils/native-require.ts +8 -8
- package/src/utils/serialize.ts +139 -146
- package/src/utils/verbose.ts +18 -18
- package/src/cli/analyze-print.ts +0 -181
- package/src/compat/middleware/manifest.ts +0 -210
- package/src/compat/next/image-client.tsx +0 -215
- package/src/compat/next/link-usage.ts +0 -29
- package/src/css/index.ts +0 -2
- package/src/render/index.ts +0 -1
- package/src/style-modules.d.ts +0 -9
|
@@ -14,241 +14,238 @@
|
|
|
14
14
|
// The output is per-route, which is invisible to the suite: it only checks each page's <link> count and
|
|
15
15
|
// computed cascade order, never cross-page asset identity.
|
|
16
16
|
|
|
17
|
-
import { statSync } from 'node:fs'
|
|
18
|
-
import { getNextConfig } from '../next/config-loader'
|
|
17
|
+
import { statSync } from 'node:fs'
|
|
18
|
+
import { getNextConfig } from '../next/config-loader'
|
|
19
19
|
|
|
20
20
|
// Merge chunks until they pass this size; avoid merging past MAX. Mirrors Next.
|
|
21
|
-
const MIN_CSS_CHUNK_SIZE = 30 * 1024
|
|
22
|
-
const MAX_CSS_CHUNK_SIZE = 100 * 1024
|
|
21
|
+
const MIN_CSS_CHUNK_SIZE = 30 * 1024
|
|
22
|
+
const MAX_CSS_CHUNK_SIZE = 100 * 1024
|
|
23
23
|
|
|
24
24
|
interface RouteCss {
|
|
25
|
-
id: string
|
|
26
|
-
cssImports: string[]
|
|
25
|
+
id: string
|
|
26
|
+
cssImports: string[]
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
function isGlobalCss(file: string) {
|
|
30
|
-
return !/\.module\.(?:css|scss|sass)$/.test(file)
|
|
30
|
+
return !/\.module\.(?:css|scss|sass)$/.test(file)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function moduleSize(file: string) {
|
|
34
34
|
try {
|
|
35
|
-
return statSync(file).size
|
|
35
|
+
return statSync(file).size
|
|
36
36
|
} catch {
|
|
37
|
-
return 0
|
|
37
|
+
return 0
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// Partition every route's ordered CSS imports into shared chunks, then project
|
|
42
42
|
// the global grouping back onto each route as ordered contiguous slices.
|
|
43
43
|
export function nextPlanRouteCssChunks(routes: RouteCss[]): Map<string, string[][]> {
|
|
44
|
-
if (nextCssChunkingMode() === 'loose') return loosePlanRouteCssChunks(routes)
|
|
44
|
+
if (nextCssChunkingMode() === 'loose') return loosePlanRouteCssChunks(routes)
|
|
45
45
|
|
|
46
|
-
const sizes = new Map<string, number>()
|
|
46
|
+
const sizes = new Map<string, number>()
|
|
47
47
|
const size = (file: string) => {
|
|
48
|
-
let value = sizes.get(file)
|
|
48
|
+
let value = sizes.get(file)
|
|
49
49
|
if (value === undefined) {
|
|
50
|
-
value = moduleSize(file)
|
|
51
|
-
sizes.set(file, value)
|
|
50
|
+
value = moduleSize(file)
|
|
51
|
+
sizes.set(file, value)
|
|
52
52
|
}
|
|
53
|
-
return value
|
|
54
|
-
}
|
|
53
|
+
return value
|
|
54
|
+
}
|
|
55
55
|
|
|
56
56
|
interface ChunkState {
|
|
57
|
-
modules: string[]
|
|
58
|
-
requests: number
|
|
57
|
+
modules: string[]
|
|
58
|
+
requests: number
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
const chunkStates: ChunkState[] = []
|
|
61
|
+
const chunkStates: ChunkState[] = []
|
|
62
62
|
// file -> (chunkState -> index within that route's ordered import list)
|
|
63
|
-
const statesByModule = new Map<string, Map<ChunkState, number>>()
|
|
63
|
+
const statesByModule = new Map<string, Map<ChunkState, number>>()
|
|
64
64
|
for (const route of routes) {
|
|
65
|
-
if (route.cssImports.length === 0) continue
|
|
66
|
-
const state: ChunkState = { modules: route.cssImports, requests: route.cssImports.length }
|
|
67
|
-
chunkStates.push(state)
|
|
65
|
+
if (route.cssImports.length === 0) continue
|
|
66
|
+
const state: ChunkState = { modules: route.cssImports, requests: route.cssImports.length }
|
|
67
|
+
chunkStates.push(state)
|
|
68
68
|
route.cssImports.forEach((file, index) => {
|
|
69
|
-
let byState = statesByModule.get(file)
|
|
69
|
+
let byState = statesByModule.get(file)
|
|
70
70
|
if (!byState) {
|
|
71
|
-
byState = new Map()
|
|
72
|
-
statesByModule.set(file, byState)
|
|
71
|
+
byState = new Map()
|
|
72
|
+
statesByModule.set(file, byState)
|
|
73
73
|
}
|
|
74
74
|
// A file may repeat within a route; the last index wins (matches Next,
|
|
75
75
|
// where a module maps to a single position per chunk group).
|
|
76
|
-
byState.set(state, index)
|
|
77
|
-
})
|
|
76
|
+
byState.set(state, index)
|
|
77
|
+
})
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// Process modules by ascending index-sum so shared prefixes seed chunks first.
|
|
81
81
|
const ordered = [...statesByModule.keys()].sort((a, b) => {
|
|
82
82
|
const sum = (file: string) => {
|
|
83
|
-
let total = 0
|
|
84
|
-
for (const index of statesByModule.get(file)!.values()) total += index
|
|
85
|
-
return total
|
|
86
|
-
}
|
|
87
|
-
return sum(a) - sum(b) || (a < b ? -1 : 1)
|
|
88
|
-
})
|
|
89
|
-
const remaining = new Set(ordered)
|
|
83
|
+
let total = 0
|
|
84
|
+
for (const index of statesByModule.get(file)!.values()) total += index
|
|
85
|
+
return total
|
|
86
|
+
}
|
|
87
|
+
return sum(a) - sum(b) || (a < b ? -1 : 1)
|
|
88
|
+
})
|
|
89
|
+
const remaining = new Set(ordered)
|
|
90
90
|
|
|
91
|
-
const chunkOfModule = new Map<string, number>()
|
|
92
|
-
let nextChunkId = 0
|
|
91
|
+
const chunkOfModule = new Map<string, number>()
|
|
92
|
+
let nextChunkId = 0
|
|
93
93
|
|
|
94
94
|
for (const startModule of remaining) {
|
|
95
|
-
let globalMode = isGlobalCss(startModule)
|
|
96
|
-
const claimed = new Map(statesByModule.get(startModule))
|
|
97
|
-
const chunkModules = new Set([startModule])
|
|
98
|
-
let currentSize = size(startModule)
|
|
95
|
+
let globalMode = isGlobalCss(startModule)
|
|
96
|
+
const claimed = new Map(statesByModule.get(startModule))
|
|
97
|
+
const chunkModules = new Set([startModule])
|
|
98
|
+
let currentSize = size(startModule)
|
|
99
99
|
|
|
100
|
-
const potential = new Map<string, Map<ChunkState, number>>()
|
|
100
|
+
const potential = new Map<string, Map<ChunkState, number>>()
|
|
101
101
|
const enqueueNext = (state: ChunkState, index: number) => {
|
|
102
|
-
const next = state.modules[index + 1]
|
|
102
|
+
const next = state.modules[index + 1]
|
|
103
103
|
if (next && remaining.has(next) && !chunkModules.has(next)) {
|
|
104
|
-
potential.set(next, statesByModule.get(next)!)
|
|
104
|
+
potential.set(next, statesByModule.get(next)!)
|
|
105
105
|
}
|
|
106
|
-
}
|
|
107
|
-
for (const [state, index] of claimed) enqueueNext(state, index)
|
|
106
|
+
}
|
|
107
|
+
for (const [state, index] of claimed) enqueueNext(state, index)
|
|
108
108
|
|
|
109
|
-
let progressed = true
|
|
109
|
+
let progressed = true
|
|
110
110
|
while (progressed) {
|
|
111
|
-
progressed = false
|
|
111
|
+
progressed = false
|
|
112
112
|
|
|
113
113
|
// Prefer the candidate that collapses the highest-request chunk group.
|
|
114
114
|
const candidates = [...potential.entries()].map(([file, states]) => {
|
|
115
|
-
let maxRequests = 0
|
|
115
|
+
let maxRequests = 0
|
|
116
116
|
for (const state of states.keys()) {
|
|
117
|
-
if (claimed.has(state)) maxRequests = Math.max(maxRequests, state.requests)
|
|
117
|
+
if (claimed.has(state)) maxRequests = Math.max(maxRequests, state.requests)
|
|
118
118
|
}
|
|
119
|
-
return { file, states, maxRequests }
|
|
120
|
-
})
|
|
121
|
-
candidates.sort((a, b) => b.maxRequests - a.maxRequests || (a.file < b.file ? -1 : 1))
|
|
119
|
+
return { file, states, maxRequests }
|
|
120
|
+
})
|
|
121
|
+
candidates.sort((a, b) => b.maxRequests - a.maxRequests || (a.file < b.file ? -1 : 1))
|
|
122
122
|
|
|
123
123
|
for (const { file, states } of candidates) {
|
|
124
|
-
const fileSize = size(file)
|
|
125
|
-
if (currentSize + fileSize > MAX_CSS_CHUNK_SIZE) continue
|
|
124
|
+
const fileSize = size(file)
|
|
125
|
+
if (currentSize + fileSize > MAX_CSS_CHUNK_SIZE) continue
|
|
126
126
|
|
|
127
127
|
// Strict order preservation: in every route sharing this module its
|
|
128
128
|
// position must be exactly one past what we've claimed there, otherwise
|
|
129
129
|
// merging would reorder or interleave stylesheets.
|
|
130
|
-
let orderOk = true
|
|
130
|
+
let orderOk = true
|
|
131
131
|
for (const [state, index] of states) {
|
|
132
|
-
const claimedIndex = claimed.get(state)
|
|
132
|
+
const claimedIndex = claimed.get(state)
|
|
133
133
|
if (claimedIndex === undefined) {
|
|
134
134
|
// A route that doesn't yet overlap: only pull it in while the chunk
|
|
135
135
|
// is still under the min-size target (Next's merge-up-to-MIN rule).
|
|
136
136
|
if (currentSize >= MIN_CSS_CHUNK_SIZE) {
|
|
137
|
-
orderOk = false
|
|
138
|
-
break
|
|
137
|
+
orderOk = false
|
|
138
|
+
break
|
|
139
139
|
}
|
|
140
140
|
} else if (claimedIndex + 1 !== index) {
|
|
141
|
-
orderOk = false
|
|
142
|
-
break
|
|
141
|
+
orderOk = false
|
|
142
|
+
break
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
|
-
if (!orderOk) continue
|
|
145
|
+
if (!orderOk) continue
|
|
146
146
|
|
|
147
147
|
// A global stylesheet must never enter a route that doesn't import it,
|
|
148
148
|
// and once the chunk carries a global it can't spread to new routes.
|
|
149
|
-
const nextIsGlobal = isGlobalCss(file)
|
|
149
|
+
const nextIsGlobal = isGlobalCss(file)
|
|
150
150
|
if (globalMode) {
|
|
151
|
-
let leaks = false
|
|
151
|
+
let leaks = false
|
|
152
152
|
for (const state of states.keys()) {
|
|
153
153
|
if (!claimed.has(state)) {
|
|
154
|
-
leaks = true
|
|
155
|
-
break
|
|
154
|
+
leaks = true
|
|
155
|
+
break
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
|
-
if (leaks) continue
|
|
158
|
+
if (leaks) continue
|
|
159
159
|
}
|
|
160
160
|
if (nextIsGlobal) {
|
|
161
|
-
let leaks = false
|
|
161
|
+
let leaks = false
|
|
162
162
|
for (const state of claimed.keys()) {
|
|
163
163
|
if (!states.has(state)) {
|
|
164
|
-
leaks = true
|
|
165
|
-
break
|
|
164
|
+
leaks = true
|
|
165
|
+
break
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
-
if (leaks) continue
|
|
168
|
+
if (leaks) continue
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
potential.delete(file)
|
|
172
|
-
currentSize += fileSize
|
|
173
|
-
if (nextIsGlobal) globalMode = true
|
|
171
|
+
potential.delete(file)
|
|
172
|
+
currentSize += fileSize
|
|
173
|
+
if (nextIsGlobal) globalMode = true
|
|
174
174
|
for (const [state, index] of states) {
|
|
175
|
-
if (claimed.has(state)) state.requests
|
|
176
|
-
claimed.set(state, index)
|
|
177
|
-
enqueueNext(state, index)
|
|
175
|
+
if (claimed.has(state)) state.requests--
|
|
176
|
+
claimed.set(state, index)
|
|
177
|
+
enqueueNext(state, index)
|
|
178
178
|
}
|
|
179
|
-
chunkModules.add(file)
|
|
180
|
-
progressed = true
|
|
181
|
-
break
|
|
179
|
+
chunkModules.add(file)
|
|
180
|
+
progressed = true
|
|
181
|
+
break
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
const chunkId = nextChunkId
|
|
185
|
+
const chunkId = nextChunkId++
|
|
186
186
|
for (const file of chunkModules) {
|
|
187
|
-
remaining.delete(file)
|
|
188
|
-
chunkOfModule.set(file, chunkId)
|
|
187
|
+
remaining.delete(file)
|
|
188
|
+
chunkOfModule.set(file, chunkId)
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
// Project the global grouping back to per-route ordered slices. A chunk's
|
|
193
193
|
// modules are contiguous in every route (guaranteed by the strict merge), so
|
|
194
194
|
// each route's imports break cleanly at chunk-id boundaries.
|
|
195
|
-
const plan = new Map<string, string[][]>()
|
|
195
|
+
const plan = new Map<string, string[][]>()
|
|
196
196
|
for (const route of routes) {
|
|
197
|
-
if (route.cssImports.length < 2) continue
|
|
198
|
-
const segments: string[][] = []
|
|
199
|
-
let current: string[] = []
|
|
200
|
-
let currentChunk = -1
|
|
197
|
+
if (route.cssImports.length < 2) continue
|
|
198
|
+
const segments: string[][] = []
|
|
199
|
+
let current: string[] = []
|
|
200
|
+
let currentChunk = -1
|
|
201
201
|
for (const file of route.cssImports) {
|
|
202
|
-
const chunkId = chunkOfModule.get(file) ?? -1
|
|
202
|
+
const chunkId = chunkOfModule.get(file) ?? -1
|
|
203
203
|
if (chunkId !== currentChunk && current.length > 0) {
|
|
204
|
-
segments.push(current)
|
|
205
|
-
current = []
|
|
204
|
+
segments.push(current)
|
|
205
|
+
current = []
|
|
206
206
|
}
|
|
207
|
-
current.push(file)
|
|
208
|
-
currentChunk = chunkId
|
|
207
|
+
current.push(file)
|
|
208
|
+
currentChunk = chunkId
|
|
209
209
|
}
|
|
210
|
-
if (current.length > 0) segments.push(current)
|
|
210
|
+
if (current.length > 0) segments.push(current)
|
|
211
211
|
// Single segment means core's default single-chunk path already suffices.
|
|
212
|
-
if (segments.length > 1) plan.set(route.id, segments)
|
|
212
|
+
if (segments.length > 1) plan.set(route.id, segments)
|
|
213
213
|
}
|
|
214
|
-
return plan
|
|
214
|
+
return plan
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
function nextCssChunkingMode(): 'loose' | 'strict' {
|
|
218
|
-
const experimental = getNextConfig().experimental as { cssChunking?: unknown } | undefined
|
|
218
|
+
const experimental = getNextConfig().experimental as { cssChunking?: unknown } | undefined
|
|
219
219
|
return experimental?.cssChunking === 'loose' || experimental?.cssChunking === undefined
|
|
220
220
|
? 'loose'
|
|
221
|
-
: 'strict'
|
|
221
|
+
: 'strict'
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
// Loose mode minimizes each route's stylesheet requests independently. A
|
|
225
225
|
// global stylesheet begins a fresh chunk so it cannot move ahead of styles
|
|
226
226
|
// imported before it; subsequent modules may share that chunk.
|
|
227
227
|
function loosePlanRouteCssChunks(routes: RouteCss[]): Map<string, string[][]> {
|
|
228
|
-
const plan = new Map<string, string[][]>()
|
|
228
|
+
const plan = new Map<string, string[][]>()
|
|
229
229
|
|
|
230
230
|
for (const route of routes) {
|
|
231
|
-
if (route.cssImports.length < 2) continue
|
|
231
|
+
if (route.cssImports.length < 2) continue
|
|
232
232
|
|
|
233
|
-
const segments: string[][] = []
|
|
234
|
-
let current: string[] = []
|
|
235
|
-
let currentSize = 0
|
|
233
|
+
const segments: string[][] = []
|
|
234
|
+
let current: string[] = []
|
|
235
|
+
let currentSize = 0
|
|
236
236
|
for (const file of route.cssImports) {
|
|
237
|
-
const size = moduleSize(file)
|
|
238
|
-
if (
|
|
239
|
-
current
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
segments.push(current);
|
|
243
|
-
current = [];
|
|
244
|
-
currentSize = 0;
|
|
237
|
+
const size = moduleSize(file)
|
|
238
|
+
if (current.length > 0 && (isGlobalCss(file) || currentSize + size > MAX_CSS_CHUNK_SIZE)) {
|
|
239
|
+
segments.push(current)
|
|
240
|
+
current = []
|
|
241
|
+
currentSize = 0
|
|
245
242
|
}
|
|
246
|
-
current.push(file)
|
|
247
|
-
currentSize += size
|
|
243
|
+
current.push(file)
|
|
244
|
+
currentSize += size
|
|
248
245
|
}
|
|
249
|
-
if (current.length > 0) segments.push(current)
|
|
250
|
-
if (segments.length > 1) plan.set(route.id, segments)
|
|
246
|
+
if (current.length > 0) segments.push(current)
|
|
247
|
+
if (segments.length > 1) plan.set(route.id, segments)
|
|
251
248
|
}
|
|
252
249
|
|
|
253
|
-
return plan
|
|
250
|
+
return plan
|
|
254
251
|
}
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
// assembly is renderer territory: the renderer calls inlineCssEnabled(config) and, when true and not
|
|
7
7
|
// dev, replaces each route/global stylesheet link with inlineCssTag(...).
|
|
8
8
|
|
|
9
|
-
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
10
|
-
import { readFileSync } from 'node:fs'
|
|
11
|
-
import type { ResolvedConfig } from '../../config'
|
|
12
|
-
import { getNextConfig } from '../next/config-loader'
|
|
9
|
+
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
10
|
+
import { readFileSync } from 'node:fs'
|
|
11
|
+
import type { ResolvedConfig } from '../../config'
|
|
12
|
+
import { getNextConfig } from '../next/config-loader'
|
|
13
13
|
|
|
14
14
|
// Inlining is a DOCUMENT optimization: Next inlines a route's CSS into the HTML
|
|
15
15
|
// it serves for a navigation to the URL, but a flight (`RSC: 1`) response for
|
|
@@ -20,20 +20,20 @@ import { getNextConfig } from '../next/config-loader';
|
|
|
20
20
|
//
|
|
21
21
|
// A scope (not a module flag) because renders are concurrent: a plain document
|
|
22
22
|
// render running alongside a flight render must keep inlining.
|
|
23
|
-
const INLINE_CSS_SUPPRESSED = Symbol.for('pnext.compat.inlineCssSuppressed')
|
|
23
|
+
const INLINE_CSS_SUPPRESSED = Symbol.for('pnext.compat.inlineCssSuppressed')
|
|
24
24
|
const suppressed = ((globalThis as Record<PropertyKey, unknown>)[INLINE_CSS_SUPPRESSED] ??=
|
|
25
|
-
new AsyncLocalStorage<true>()) as AsyncLocalStorage<true
|
|
25
|
+
new AsyncLocalStorage<true>()) as AsyncLocalStorage<true>
|
|
26
26
|
|
|
27
27
|
/** Run `render` with CSS inlining disabled (flight responses — see above). */
|
|
28
28
|
export function withoutInlineCss<T>(render: () => T): T {
|
|
29
|
-
return suppressed.run(true, render)
|
|
29
|
+
return suppressed.run(true, render)
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/** True when `experimental.inlineCss` is set in next.config. */
|
|
33
33
|
export function inlineCssEnabled(_config: ResolvedConfig): boolean {
|
|
34
|
-
const config = getNextConfig()
|
|
35
|
-
const experimental = config.experimental as { inlineCss?: unknown } | undefined
|
|
36
|
-
return experimental?.inlineCss === true
|
|
34
|
+
const config = getNextConfig()
|
|
35
|
+
const experimental = config.experimental as { inlineCss?: unknown } | undefined
|
|
36
|
+
return experimental?.inlineCss === true
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -42,32 +42,32 @@ export function inlineCssEnabled(_config: ResolvedConfig): boolean {
|
|
|
42
42
|
* Returns '' if the file can't be read (never fail the page over inlining).
|
|
43
43
|
*/
|
|
44
44
|
export function inlineCssTag(assetFile: string, nonce?: string): string {
|
|
45
|
-
const css = readCss(assetFile)
|
|
46
|
-
return css === undefined ? '' : inlineStyleTag(css, nonce)
|
|
45
|
+
const css = readCss(assetFile)
|
|
46
|
+
return css === undefined ? '' : inlineStyleTag(css, nonce)
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function readCss(assetFile: string): string | undefined {
|
|
50
50
|
try {
|
|
51
|
-
return readFileSync(assetFile, 'utf8')
|
|
51
|
+
return readFileSync(assetFile, 'utf8')
|
|
52
52
|
} catch {
|
|
53
|
-
return undefined
|
|
53
|
+
return undefined
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
function inlineStyleTag(css: string, nonce?: string): string {
|
|
58
|
-
const nonceAttr = nonce ? ` nonce="${nonce}"` : ''
|
|
59
|
-
return `<style data-pnext-inline-css${nonceAttr}>${css}</style
|
|
58
|
+
const nonceAttr = nonce ? ` nonce="${nonce}"` : ''
|
|
59
|
+
return `<style data-pnext-inline-css${nonceAttr}>${css}</style>`
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
export function inlineCssStylesheets(
|
|
63
63
|
config: ResolvedConfig,
|
|
64
64
|
options: { assetNames: string[]; dev: boolean; nonce?: string; prependCss?: string },
|
|
65
65
|
): string[] | undefined {
|
|
66
|
-
if (options.dev || suppressed.getStore() === true || !inlineCssEnabled(config)) return undefined
|
|
66
|
+
if (options.dev || suppressed.getStore() === true || !inlineCssEnabled(config)) return undefined
|
|
67
67
|
const assets = options.assetNames.map(asset =>
|
|
68
68
|
readCss(`${config.outPath}/public/assets/${asset}`),
|
|
69
|
-
)
|
|
70
|
-
if (assets.some(css => css === undefined)) return undefined
|
|
71
|
-
const css = [options.prependCss, ...assets].filter(Boolean).join('\n')
|
|
72
|
-
return css ? [inlineStyleTag(css, options.nonce)] : []
|
|
69
|
+
)
|
|
70
|
+
if (assets.some(css => css === undefined)) return undefined
|
|
71
|
+
const css = [options.prependCss, ...assets].filter(Boolean).join('\n')
|
|
72
|
+
return css ? [inlineStyleTag(css, options.nonce)] : []
|
|
73
73
|
}
|
|
@@ -9,52 +9,52 @@
|
|
|
9
9
|
//
|
|
10
10
|
// Zero-cost when disabled or when the app has no lightningcss install: the source passes through.
|
|
11
11
|
|
|
12
|
-
import { createRequire } from 'node:module'
|
|
13
|
-
import path from 'node:path'
|
|
14
|
-
import { loadNative } from '../../utils/native-require'
|
|
15
|
-
import { getNextConfig } from '../next/config-loader'
|
|
12
|
+
import { createRequire } from 'node:module'
|
|
13
|
+
import path from 'node:path'
|
|
14
|
+
import { loadNative } from '../../utils/native-require'
|
|
15
|
+
import { getNextConfig } from '../next/config-loader'
|
|
16
16
|
|
|
17
17
|
interface LightningModule {
|
|
18
18
|
transform(options: {
|
|
19
|
-
filename: string
|
|
20
|
-
code: Uint8Array
|
|
21
|
-
include?: number
|
|
22
|
-
exclude?: number
|
|
23
|
-
errorRecovery?: boolean
|
|
24
|
-
}): { code: Uint8Array }
|
|
25
|
-
Features: Record<string, number
|
|
19
|
+
filename: string
|
|
20
|
+
code: Uint8Array
|
|
21
|
+
include?: number
|
|
22
|
+
exclude?: number
|
|
23
|
+
errorRecovery?: boolean
|
|
24
|
+
}): { code: Uint8Array }
|
|
25
|
+
Features: Record<string, number>
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
interface LightningFeaturesConfig {
|
|
29
|
-
include?: string[]
|
|
30
|
-
exclude?: string[]
|
|
29
|
+
include?: string[]
|
|
30
|
+
exclude?: string[]
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const moduleCache = new Map<string, LightningModule | null>()
|
|
33
|
+
const moduleCache = new Map<string, LightningModule | null>()
|
|
34
34
|
|
|
35
35
|
function loadLightningcss(root: string): LightningModule | null {
|
|
36
|
-
const cached = moduleCache.get(root)
|
|
37
|
-
if (cached !== undefined) return cached
|
|
38
|
-
let loaded: LightningModule | null = null
|
|
36
|
+
const cached = moduleCache.get(root)
|
|
37
|
+
if (cached !== undefined) return cached
|
|
38
|
+
let loaded: LightningModule | null = null
|
|
39
39
|
try {
|
|
40
|
-
const require = createRequire(path.join(root, 'package.json'))
|
|
41
|
-
loaded = loadNative(() => require('lightningcss') as LightningModule)
|
|
40
|
+
const require = createRequire(path.join(root, 'package.json'))
|
|
41
|
+
loaded = loadNative(() => require('lightningcss') as LightningModule)
|
|
42
42
|
} catch {
|
|
43
|
-
loaded = null
|
|
43
|
+
loaded = null
|
|
44
44
|
}
|
|
45
|
-
moduleCache.set(root, loaded)
|
|
46
|
-
return loaded
|
|
45
|
+
moduleCache.set(root, loaded)
|
|
46
|
+
return loaded
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/** `'light-dark'` -> `LightDark` (lightningcss `Features` enum key). */
|
|
50
50
|
function featureKey(name: string): string {
|
|
51
|
-
return name.replace(/(?:^|-)([a-z0-9])/g, (_match, char: string) => char.toUpperCase())
|
|
51
|
+
return name.replace(/(?:^|-)([a-z0-9])/g, (_match, char: string) => char.toUpperCase())
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
function featureMask(features: Record<string, number>, names: string[] | undefined): number {
|
|
55
|
-
let mask = 0
|
|
56
|
-
for (const name of names ?? []) mask |= features[featureKey(name)] ?? 0
|
|
57
|
-
return mask
|
|
55
|
+
let mask = 0
|
|
56
|
+
for (const name of names ?? []) mask |= features[featureKey(name)] ?? 0
|
|
57
|
+
return mask
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/**
|
|
@@ -64,17 +64,16 @@ function featureMask(features: Record<string, number>, names: string[] | undefin
|
|
|
64
64
|
*/
|
|
65
65
|
export function maybeLightningcssTransform(css: string, file: string, root: string): string {
|
|
66
66
|
const experimental = getNextConfig().experimental as
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (!lightning) return css;
|
|
67
|
+
{ useLightningcss?: boolean; lightningCssFeatures?: LightningFeaturesConfig } | undefined
|
|
68
|
+
if (experimental?.useLightningcss !== true) return css
|
|
69
|
+
const lightning = loadLightningcss(root)
|
|
70
|
+
if (!lightning) return css
|
|
72
71
|
|
|
73
|
-
const features = experimental.lightningCssFeatures
|
|
74
|
-
const userInclude = featureMask(lightning.Features, features?.include)
|
|
75
|
-
const userExclude = featureMask(lightning.Features, features?.exclude)
|
|
72
|
+
const features = experimental.lightningCssFeatures
|
|
73
|
+
const userInclude = featureMask(lightning.Features, features?.include)
|
|
74
|
+
const userExclude = featureMask(lightning.Features, features?.exclude)
|
|
76
75
|
// Nesting always transpiles (Next hardcodes it), user excludes win.
|
|
77
|
-
const include = ((lightning.Features.Nesting ?? 1) | userInclude) & ~userExclude
|
|
76
|
+
const include = ((lightning.Features.Nesting ?? 1) | userInclude) & ~userExclude
|
|
78
77
|
|
|
79
78
|
try {
|
|
80
79
|
const result = lightning.transform({
|
|
@@ -83,9 +82,9 @@ export function maybeLightningcssTransform(css: string, file: string, root: stri
|
|
|
83
82
|
include,
|
|
84
83
|
exclude: userExclude,
|
|
85
84
|
errorRecovery: true,
|
|
86
|
-
})
|
|
87
|
-
return new TextDecoder().decode(result.code)
|
|
85
|
+
})
|
|
86
|
+
return new TextDecoder().decode(result.code)
|
|
88
87
|
} catch {
|
|
89
|
-
return css
|
|
88
|
+
return css
|
|
90
89
|
}
|
|
91
90
|
}
|