Skip to content

Commit

Permalink
fixes to allow lazy compilation for import()
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Dec 13, 2021
1 parent 4c84150 commit e1245f3
Show file tree
Hide file tree
Showing 41 changed files with 673 additions and 363 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Expand Up @@ -12,6 +12,7 @@ examples/with-jest/**
examples/with-mobx-state-tree/**
examples/with-mobx/**
packages/next/bundles/webpack/packages/*.runtime.js
packages/next/bundles/webpack/packages/lazy-compilation-*.js
packages/next/compiled/**/*
packages/react-refresh-utils/**/*.js
packages/react-dev-overlay/lib/**
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Expand Up @@ -3,6 +3,7 @@ node_modules
**/_next/**
**/dist/**
packages/next/bundles/webpack/packages/*.runtime.js
packages/next/bundles/webpack/packages/lazy-compilation-*.js
packages/next/compiled/**
packages/react-refresh-utils/**/*.js
packages/react-refresh-utils/**/*.d.ts
Expand Down
10 changes: 9 additions & 1 deletion packages/next-swc/crates/core/src/lib.rs
Expand Up @@ -79,6 +79,9 @@ pub struct TransformOptions {
#[serde(default)]
pub is_development: bool,

#[serde(default)]
pub is_server: bool,

#[serde(default)]
pub styled_components: Option<styled_components::Config>,

Expand Down Expand Up @@ -113,7 +116,12 @@ pub fn custom_before_pass(file: Arc<SourceFile>, opts: &TransformOptions) -> imp
},
Optional::new(next_ssg::next_ssg(), !opts.disable_next_ssg),
amp_attributes::amp_attributes(),
next_dynamic::next_dynamic(file.name.clone(), opts.pages_dir.clone()),
next_dynamic::next_dynamic(
opts.is_development,
opts.is_server,
file.name.clone(),
opts.pages_dir.clone()
),
Optional::new(
page_config::page_config(opts.is_development, opts.is_page_file),
!opts.disable_page_config
Expand Down
458 changes: 241 additions & 217 deletions packages/next-swc/crates/core/src/next_dynamic.rs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/next-swc/crates/core/tests/errors.rs
Expand Up @@ -32,6 +32,8 @@ fn next_dynamic_errors(input: PathBuf) {
syntax(),
&|_tr| {
next_dynamic(
true,
false,
FileName::Real(PathBuf::from("/some-project/src/some-file.js")),
Some("/some-project/src".into()),
)
Expand Down
20 changes: 18 additions & 2 deletions packages/next-swc/crates/core/tests/fixture.rs
Expand Up @@ -33,17 +33,33 @@ fn amp_attributes_fixture(input: PathBuf) {

#[fixture("tests/fixture/next-dynamic/**/input.js")]
fn next_dynamic_fixture(input: PathBuf) {
let output = input.parent().unwrap().join("output.js");
let output_dev = input.parent().unwrap().join("output-dev.js");
let output_prod = input.parent().unwrap().join("output-prod.js");
test_fixture(
syntax(),
&|_tr| {
next_dynamic(
true,
false,
FileName::Real(PathBuf::from("/some-project/src/some-file.js")),
Some("/some-project/src".into()),
)
},
&input,
&output,
&output_dev,
);
test_fixture(
syntax(),
&|_tr| {
next_dynamic(
false,
false,
FileName::Real(PathBuf::from("/some-project/src/some-file.js")),
Some("/some-project/src".into()),
)
},
&input,
&output_prod,
);
}

Expand Down
@@ -0,0 +1,12 @@
import dynamic1 from 'next/dynamic'
import dynamic2 from 'next/dynamic'
const DynamicComponent1 = dynamic1(() => import('../components/hello1'), {
loadableGenerated: {
modules: ['some-file.js -> ' + '../components/hello1'],
},
})
const DynamicComponent2 = dynamic2(() => import('../components/hello2'), {
loadableGenerated: {
modules: ['some-file.js -> ' + '../components/hello2'],
},
})
Expand Up @@ -3,12 +3,10 @@ import dynamic2 from 'next/dynamic'
const DynamicComponent1 = dynamic1(() => import('../components/hello1'), {
loadableGenerated: {
webpack: () => [require.resolveWeak('../components/hello1')],
modules: ['some-file.js -> ' + '../components/hello1'],
},
})
const DynamicComponent2 = dynamic2(() => import('../components/hello2'), {
loadableGenerated: {
webpack: () => [require.resolveWeak('../components/hello2')],
modules: ['some-file.js -> ' + '../components/hello2'],
},
})
@@ -0,0 +1,8 @@
import dynamic from 'next/dynamic'
import somethingElse from 'something-else'
const DynamicComponent = dynamic(() => import('../components/hello'), {
loadableGenerated: {
modules: ['some-file.js -> ' + '../components/hello'],
},
})
somethingElse.dynamic('should not be transformed')
Expand Up @@ -3,7 +3,6 @@ import somethingElse from 'something-else'
const DynamicComponent = dynamic(() => import('../components/hello'), {
loadableGenerated: {
webpack: () => [require.resolveWeak('../components/hello')],
modules: ['some-file.js -> ' + '../components/hello'],
},
})
somethingElse.dynamic('should not be transformed')
@@ -0,0 +1,6 @@
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() => import('../components/hello'), {
loadableGenerated: {
modules: ['some-file.js -> ' + '../components/hello'],
},
})
Expand Up @@ -2,6 +2,5 @@ import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() => import('../components/hello'), {
loadableGenerated: {
webpack: () => [require.resolveWeak('../components/hello')],
modules: ['some-file.js -> ' + '../components/hello'],
},
})
@@ -0,0 +1,10 @@
import dynamic from "next/dynamic";
const DynamicComponentWithCustomLoading = dynamic(()=>import("../components/hello")
, {
loadableGenerated: {
modules: [
"some-file.js -> " + "../components/hello"
]
},
loading: ()=><p >...</p>
});
Expand Up @@ -5,10 +5,6 @@ const DynamicComponentWithCustomLoading = dynamic(()=>import("../components/hell
webpack: ()=>[
require.resolveWeak("../components/hello")
]
,
modules: [
"some-file.js -> " + "../components/hello"
]
},
loading: ()=><p >...</p>
});
@@ -0,0 +1,12 @@
import dynamic from "next/dynamic";
const DynamicComponent = dynamic(()=>handleImport(import("./components/hello"))
, {
loadableGenerated: {
modules: [
"some-file.js -> " + "./components/hello"
]
},
loading: ()=>null
,
ssr: false
});
Expand Up @@ -5,10 +5,6 @@ const DynamicComponent = dynamic(()=>handleImport(import("./components/hello"))
webpack: ()=>[
require.resolveWeak("./components/hello")
]
,
modules: [
"some-file.js -> " + "./components/hello"
]
},
loading: ()=>null
,
Expand Down
1 change: 1 addition & 0 deletions packages/next-swc/crates/core/tests/full.rs
Expand Up @@ -55,6 +55,7 @@ fn test(input: &Path, minify: bool) {
pages_dir: None,
is_page_file: false,
is_development: true,
is_server: false,
styled_components: Some(assert_json("{}")),
remove_console: None,
react_remove_properties: None,
Expand Down
50 changes: 28 additions & 22 deletions packages/next/build/babel/plugins/react-loadable-plugin.ts
Expand Up @@ -168,29 +168,35 @@ export default function ({
options.node.properties.push(
t.objectProperty(
t.identifier('loadableGenerated'),
t.objectExpression([
t.objectProperty(
t.identifier('webpack'),
t.arrowFunctionExpression(
[],
t.arrayExpression(
dynamicImports.map((dynamicImport) => {
return t.callExpression(
t.memberExpression(
t.identifier('require'),
t.identifier('resolveWeak')
),
[dynamicImport]
t.objectExpression(
state.file.opts.caller?.isDev ||
state.file.opts.caller?.isServer
? [
t.objectProperty(
t.identifier('modules'),
t.arrayExpression(dynamicKeys)
),
]
: [
t.objectProperty(
t.identifier('webpack'),
t.arrowFunctionExpression(
[],
t.arrayExpression(
dynamicImports.map((dynamicImport) => {
return t.callExpression(
t.memberExpression(
t.identifier('require'),
t.identifier('resolveWeak')
),
[dynamicImport]
)
})
)
)
})
)
)
),
t.objectProperty(
t.identifier('modules'),
t.arrayExpression(dynamicKeys)
),
])
),
]
)
)
)

Expand Down
2 changes: 2 additions & 0 deletions packages/next/build/swc/options.js
Expand Up @@ -141,6 +141,7 @@ export function getLoaderSWCOptions({
disableNextSsg: true,
disablePageConfig: true,
isDevelopment: development,
isServer,
pagesDir,
isPageFile,
env: {
Expand All @@ -165,6 +166,7 @@ export function getLoaderSWCOptions({
: {}),
disableNextSsg: !isPageFile,
isDevelopment: development,
isServer,
pagesDir,
isPageFile,
}
Expand Down
16 changes: 16 additions & 0 deletions packages/next/build/webpack-config.ts
Expand Up @@ -1402,6 +1402,7 @@ export default async function getBaseWebpackConfig(
runtimeAsset: hasConcurrentFeatures
? `server/${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js`
: undefined,
dev,
}),
targetWeb && new DropClientPage(),
config.outputFileTracing &&
Expand Down Expand Up @@ -1733,6 +1734,21 @@ export default async function getBaseWebpackConfig(
devtoolRevertWarning(originalDevtool)
}

// eslint-disable-next-line no-shadow
const webpack5Config = webpackConfig as webpack5.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 (typeof (webpackConfig as any).then === 'function') {
console.warn(
'> Promise returned in next config. https://nextjs.org/docs/messages/promise-in-next-config'
Expand Down
15 changes: 12 additions & 3 deletions packages/next/build/webpack/plugins/react-loadable-plugin.ts
Expand Up @@ -53,7 +53,8 @@ function getChunkGroupFromBlock(
function buildManifest(
_compiler: webpack.Compiler,
compilation: webpack.compilation.Compilation,
pagesDir: string
pagesDir: string,
dev: boolean
) {
let manifest: { [k: string]: { id: string | number; files: string[] } } = {}

Expand Down Expand Up @@ -125,7 +126,7 @@ function buildManifest(
// next/dynamic so they are loaded by the same technique

// add the id and files to the manifest
const id = getModuleId(compilation, module)
const id = dev ? key : getModuleId(compilation, module)
manifest[key] = { id, files: Array.from(files) }
}
}
Expand All @@ -146,19 +147,27 @@ export class ReactLoadablePlugin {
private filename: string
private pagesDir: string
private runtimeAsset?: string
private dev: boolean

constructor(opts: {
filename: string
pagesDir: string
runtimeAsset?: string
dev: boolean
}) {
this.filename = opts.filename
this.pagesDir = opts.pagesDir
this.runtimeAsset = opts.runtimeAsset
this.dev = opts.dev
}

createAssets(compiler: any, compilation: any, assets: any) {
const manifest = buildManifest(compiler, compilation, this.pagesDir)
const manifest = buildManifest(
compiler,
compilation,
this.pagesDir,
this.dev
)
// @ts-ignore: TODO: remove when webpack 5 is stable
assets[this.filename] = new sources.RawSource(
JSON.stringify(manifest, null, 2)
Expand Down
40 changes: 40 additions & 0 deletions packages/next/bundles/webpack/packages/lazy-compilation-node.js
@@ -0,0 +1,40 @@
/* global __resourceQuery */

"use strict";

var urlBase = decodeURIComponent(__resourceQuery.slice(1));
exports.keepAlive = function (options) {
var data = options.data;
var onError = options.onError;
var active = options.active;
var module = options.module;
var response;
var request = (
urlBase.startsWith("https") ? require("https") : require("http")
).request(
urlBase + data,
{
agent: false,
headers: { accept: "text/event-stream" }
},
function (res) {
response = res;
response.on("error", errorHandler);
if (!active && !module.hot) {
console.log(
"Hot Module Replacement is not enabled. Waiting for process restart..."
);
}
}
);
function errorHandler(err) {
err.message =
"Problem communicating active modules to the server: " + err.message;
onError(err);
}
request.on("error", errorHandler);
request.end();
return function () {
response.destroy();
};
};

0 comments on commit e1245f3

Please sign in to comment.