Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable css import in rsc server side #38418

Merged
merged 10 commits into from Jul 11, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -6,15 +6,14 @@ export default async function transformSource(this: any): Promise<string> {
modules = modules ? [modules] : []
}

const requests = modules as string[]
const code =
modules
.map(
(request: string) => `import(/* webpackMode: "eager" */ '${request}')`
)
requests
.map((request) => `import(/* webpackMode: "eager" */ '${request}')`)
.join(';\n') +
`
export const __next_rsc_css__ = ${JSON.stringify(
modules.filter((file: string) => file.endsWith('.css'))
requests.filter((request) => request.endsWith('.css'))
)};
export const __next_rsc__ = {
server: false,
Expand Down
37 changes: 21 additions & 16 deletions packages/next/build/webpack/plugins/flight-manifest-plugin.ts
Expand Up @@ -9,7 +9,6 @@ import { webpack, sources } from 'next/dist/compiled/webpack/webpack'
import { FLIGHT_MANIFEST } from '../../../shared/lib/constants'
import { clientComponentRegex } from '../loaders/utils'
import { relative } from 'path'
import { getEntrypointFiles } from './build-manifest-plugin'
import type { webpack5 } from 'next/dist/compiled/webpack/webpack'

// This is the module that will be used to anchor all client references to.
Expand Down Expand Up @@ -187,29 +186,35 @@ export class FlightManifestPlugin {
.filter((name) => name !== null)

// Get all CSS files imported from the module's dependencies.
const visited = new Set()
const visitedCss = new Set()
huozhi marked this conversation as resolved.
Show resolved Hide resolved
const cssChunks: string[] = []
function findCSSDeps(module: any) {

function collectClientImportedCss(module: any) {
if (!module) return

const modRequest = module.userRequest
if (visited.has(modRequest)) return
visited.add(modRequest)
if (visitedCss.has(modRequest)) return
visitedCss.add(modRequest)

if (/(?<!\.module)\.css$/.test(modRequest)) {
cssChunks.push(modRequest)
if (/\.css$/.test(modRequest)) {
// collect relative imported css chunks
compilation.chunkGraph.getModuleChunks(module).forEach((c) => {
;[...c.files]
.filter((file) => file.endsWith('.css'))
.forEach((file) => cssChunks.push(file))
})
}

compilation.moduleGraph
.getOutgoingConnections(module)
// @ts-ignore
.forEach((connection: any) => {
findCSSDeps(
compilation.moduleGraph.getResolvedModule(connection.dependency)
)
})
const connections = Array.from(
compilation.moduleGraph.getOutgoingConnections(module)
)
connections.forEach((connection) => {
collectClientImportedCss(
compilation.moduleGraph.getResolvedModule(connection.dependency!)
)
})
}
findCSSDeps(mod)
collectClientImportedCss(mod)

moduleExportedKeys.forEach((name) => {
let requiredChunks = []
Expand Down
6 changes: 4 additions & 2 deletions packages/next/client/app-index.tsx
Expand Up @@ -122,8 +122,10 @@ function useInitialServerResponse(cacheKey: string) {
return (self as any).__next_chunk_load__(chunkId)
})
)
// import css
;(self as any).__next_require__(data.id)
// import css in dev when it's wrapped by style loader
if (process.env.NODE_ENV === 'development') {
;(self as any).__next_require__(data.id)
}
huozhi marked this conversation as resolved.
Show resolved Hide resolved
}

const loadCssFromStreamData = (data: string) => {
Expand Down
18 changes: 16 additions & 2 deletions packages/next/server/app-render.tsx
Expand Up @@ -333,8 +333,22 @@ function getCssFlight(ComponentMod: any, serverComponentManifest: any) {
const importedServerCSSFiles: string[] =
ComponentMod.__client__?.__next_rsc_css__ || []

const cssFlight = importedServerCSSFiles
.map((css) => `CSS:${JSON.stringify(serverComponentManifest[css].default)}`)
const cssFiles = importedServerCSSFiles.map(
(css) => serverComponentManifest[css].default
)
if (process.env.NODE_ENV === 'development') {
return cssFiles.map((css) => `CSS:${JSON.stringify(css)}`).join('\n')
}

const cssSet = cssFiles.reduce((res, css) => {
res.add(...css.chunks)
return res
}, new Set())

const cssFlight = Array.from(cssSet)
.map(
(css) => `CSS:${JSON.stringify({ id: 'css', name: '', chunks: [css] })}`
huozhi marked this conversation as resolved.
Show resolved Hide resolved
)
.join('\n')
return cssFlight
}
Expand Down
3 changes: 3 additions & 0 deletions test/e2e/app-dir/app/app/dashboard/global.css
@@ -0,0 +1,3 @@
.dangerous-text {
color: red;
}
5 changes: 3 additions & 2 deletions test/e2e/app-dir/app/app/dashboard/layout.server.js
@@ -1,10 +1,11 @@
import './style.css'
import './global.css'

export default function DashboardLayout(props) {
return (
<>
<div className="dangerous-text">
<h1 className="green">Dashboard</h1>
{props.children}
</>
</div>
)
}