Skip to content

Commit

Permalink
detect node_module pkg
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed Apr 7, 2022
1 parent 2012286 commit e8915de
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 19 deletions.
45 changes: 37 additions & 8 deletions packages/next/build/webpack/loaders/next-flight-server-loader.ts
Expand Up @@ -41,13 +41,15 @@ async function parseModuleInfo({
isClientCompilation,
isServerComponent,
isClientComponent,
resolver,
}: {
resourcePath: string
source: string
isClientCompilation: boolean
extensions: string[]
isServerComponent: (name: string) => boolean
isClientComponent: (name: string) => boolean
resolver: (req: string) => Promise<string>
}): Promise<{
source: string
imports: string[]
Expand All @@ -73,6 +75,16 @@ async function parseModuleInfo({
switch (node.type) {
case 'ImportDeclaration':
const importSource = node.source.value
const resolvedPath = await resolver(importSource)
const isNodeModuleImport = resolvedPath.includes('/node_modules/')

// matching node_module package but excluding react cores since react is required to be shared
const isReactImports = [
'react',
'react/jsx-runtime',
'react/jsx-dev-runtime',
].includes(importSource)

if (!isClientCompilation) {
// Server compilation for .server.js.
if (isServerComponent(importSource)) {
Expand All @@ -92,25 +104,29 @@ async function parseModuleInfo({
imports.push(importSource)
} else {
// A shared component. It should be handled as a server component.
const serverImportSource = createFlightServerRequest(
importSource,
extensions
)
const serverImportSource = isReactImports
? importSource
: createFlightServerRequest(importSource, extensions)
transformedSource += importDeclarations
transformedSource += JSON.stringify(serverImportSource)
imports.push(importSource)

// TODO: support handling RSC components from node_modules
if (!isNodeModuleImport) {
imports.push(importSource)
}
}
} else {
// For the client compilation, we skip all modules imports but
// always keep client/shared components in the bundle. All client components
// have to be imported from either server or client components.
if (
isServerComponent(importSource) ||
hasFlightLoader(importSource, 'server')
hasFlightLoader(importSource, 'server') // ||
// TODO: support handling RSC components from node_modules
// isNodeModuleImport
) {
continue
}

imports.push(importSource)
}

Expand Down Expand Up @@ -159,7 +175,16 @@ export default async function transformSource(
source: string
): Promise<string> {
const { client: isClientCompilation, extensions } = this.getOptions()
const { resourcePath } = this
const { resourcePath, resolve: resolveFn, context } = this

const resolver = (req: string): Promise<string> => {
return new Promise((resolve, reject) => {
resolveFn(context, req, (err: any, result: string) => {
if (err) return reject(err)
resolve(result)
})
})
}

if (typeof source !== 'string') {
throw new Error('Expected source to have been transformed to a string.')
Expand Down Expand Up @@ -192,6 +217,7 @@ export default async function transformSource(
isClientCompilation,
isServerComponent,
isClientComponent,
resolver,
})

/**
Expand Down Expand Up @@ -234,5 +260,8 @@ export default async function transformSource(
}

const output = transformedSource + '\n' + buildExports(rscExports, isEsm)
// if (resourcePath.includes('external-imports')) {
// console.log(isClientCompilation ? 'client' : 'server', '\n' ,output)
// }
return output
}
@@ -1,12 +1,8 @@
import Link from 'next/link'
import { Text } from 'esm-client-component'

export default function Nav() {
return (
<>
<div>
<Text text={`nav-title`} />
</div>
<div>
<Link href={'/next-api/link'}>
<a id="goto-next-link">next link</a>
Expand Down
@@ -1,6 +1,8 @@
import { useState } from 'react'
import Client from './client.client'

const random = ~~(Math.random() * 10000)

export default function Shared() {
let isServerComponent
try {
Expand All @@ -12,7 +14,8 @@ export default function Shared() {

return (
<>
<Client />, {isServerComponent ? 'shared:server' : 'shared:client'}
<Client />,{' '}
{(isServerComponent ? 'shared:server' : 'shared:client') + ':' + random}
</>
)
}
@@ -1,11 +1,9 @@
import moment from 'moment'
import nonIsomorphicText from 'non-isomorphic-text'

export default function Page() {
return (
<div>
<div>date:{moment().toString()}</div>
<div>{nonIsomorphicText()}</div>
<div>date:{nonIsomorphicText()}</div>
</div>
)
}
Expand Up @@ -56,8 +56,8 @@ export default function (context, { runtime, env }) {

// Should have 2 occurrences of "shared:server", and 2 occurrences of
// "shared:client".
const sharedServerModule = [...main.matchAll(/shared:server/g)]
const sharedClientModule = [...main.matchAll(/shared:client/g)]
const sharedServerModule = [...main.matchAll(/shared:server:(\d+)/g)]
const sharedClientModule = [...main.matchAll(/shared:client:(\d+)/g)]
expect(sharedServerModule.length).toBe(2)
expect(sharedClientModule.length).toBe(2)

Expand Down Expand Up @@ -184,7 +184,7 @@ export default function (context, { runtime, env }) {
.readFileSync(join(distServerDir, 'external-imports.js'))
.toString()

expect(bundle).not.toContain('moment')
expect(bundle).not.toContain('non-isomorphic-text')
})
}

Expand Down

0 comments on commit e8915de

Please sign in to comment.