mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Add node_modules bundling under the --lambdas flag for next build (#5690)
* Add node_modules bundling under the —lambdas flag for next build * Run minifier when lambdas mode is enabled * Add lambdas option to next.config.js * Add test for lambdas option
This commit is contained in:
parent
b63dda7cf7
commit
7d78c3b641
|
@ -7,9 +7,10 @@ import { printAndExit } from '../server/lib/utils'
|
|||
|
||||
const argv = parseArgs(process.argv.slice(2), {
|
||||
alias: {
|
||||
h: 'help'
|
||||
h: 'help',
|
||||
l: 'lambdas'
|
||||
},
|
||||
boolean: ['h']
|
||||
boolean: ['h', 'l']
|
||||
})
|
||||
|
||||
if (argv.help) {
|
||||
|
@ -28,6 +29,7 @@ if (argv.help) {
|
|||
}
|
||||
|
||||
const dir = resolve(argv._[0] || '.')
|
||||
const lambdas = argv.lambdas
|
||||
|
||||
// Check if pages dir exists and warn if not
|
||||
if (!existsSync(dir)) {
|
||||
|
@ -42,7 +44,7 @@ if (!existsSync(join(dir, 'pages'))) {
|
|||
printAndExit('> Couldn\'t find a `pages` directory. Please create one under the project root')
|
||||
}
|
||||
|
||||
build(dir)
|
||||
build(dir, null, lambdas)
|
||||
.catch((err) => {
|
||||
printAndExit(err)
|
||||
})
|
||||
|
|
|
@ -32,8 +32,9 @@ async function ensureProjectDirectoryIsWriteAble (dir) {
|
|||
}
|
||||
}
|
||||
|
||||
export default async function build (dir, conf = null) {
|
||||
export default async function build (dir, conf = null, lambdas = false) {
|
||||
const config = loadConfig(PHASE_PRODUCTION_BUILD, dir, conf)
|
||||
const lambdasOption = config.lambdas ? config.lambdas : lambdas
|
||||
const distDir = join(dir, config.distDir)
|
||||
const buildId = await generateBuildId(config.generateBuildId, nanoid)
|
||||
|
||||
|
@ -41,8 +42,8 @@ export default async function build (dir, conf = null) {
|
|||
|
||||
try {
|
||||
const configs = await Promise.all([
|
||||
getBaseWebpackConfig(dir, { buildId, isServer: false, config }),
|
||||
getBaseWebpackConfig(dir, { buildId, isServer: true, config })
|
||||
getBaseWebpackConfig(dir, { buildId, isServer: false, config, lambdas: lambdasOption }),
|
||||
getBaseWebpackConfig(dir, { buildId, isServer: true, config, lambdas: lambdasOption })
|
||||
])
|
||||
|
||||
await runCompiler(configs)
|
||||
|
|
|
@ -25,13 +25,41 @@ import AssetsSizePlugin from './webpack/plugins/assets-size-plugin'
|
|||
// The externals config makes sure that
|
||||
// on the server side when modules are
|
||||
// in node_modules they don't get compiled by webpack
|
||||
function externalsConfig (dir, isServer) {
|
||||
function externalsConfig (dir, isServer, lambdas) {
|
||||
const externals = []
|
||||
|
||||
if (!isServer) {
|
||||
return externals
|
||||
}
|
||||
|
||||
// When lambdas mode is enabled all node_modules will be compiled into the server bundles
|
||||
// So that all dependencies can be devDependencies and are not required to be installed
|
||||
if (lambdas) {
|
||||
return [
|
||||
(context, request, callback) => {
|
||||
resolve(request, { basedir: context, preserveSymlinks: true }, (err, res) => {
|
||||
if (err) {
|
||||
return callback()
|
||||
}
|
||||
if (res.match(/next-server[/\\]dist[/\\]lib[/\\]head/)) {
|
||||
return callback(null, `commonjs next-server/dist/lib/head.js`)
|
||||
}
|
||||
if (res.match(/next-server[/\\]dist[/\\]lib[/\\]asset/)) {
|
||||
return callback(null, `commonjs next-server/dist/lib/asset.js`)
|
||||
}
|
||||
if (res.match(/next-server[/\\]dist[/\\]lib[/\\]runtime-config/)) {
|
||||
return callback(null, `commonjs next-server/dist/lib/runtime-config.js`)
|
||||
}
|
||||
// Default pages have to be transpiled
|
||||
if (res.match(/next-server[/\\]dist[/\\]lib[/\\]loadable/)) {
|
||||
return callback(null, `commonjs next-server/dist/lib/loadable.js`)
|
||||
}
|
||||
callback()
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const notExternalModules = ['next/app', 'next/document', 'next/error', 'http-status', 'string-hash']
|
||||
|
||||
externals.push((context, request, callback) => {
|
||||
|
@ -74,7 +102,26 @@ function externalsConfig (dir, isServer) {
|
|||
return externals
|
||||
}
|
||||
|
||||
function optimizationConfig ({dir, dev, isServer, totalPages}) {
|
||||
function optimizationConfig ({dir, dev, isServer, totalPages, lambdas}) {
|
||||
if (isServer && lambdas) {
|
||||
return {
|
||||
splitChunks: false,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
parallel: true,
|
||||
sourceMap: false,
|
||||
cache: true,
|
||||
cacheKeys: (keys) => {
|
||||
// path changes per build because we add buildId
|
||||
// because the input is already hashed the path is not needed
|
||||
delete keys.path
|
||||
return keys
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (isServer) {
|
||||
return {
|
||||
splitChunks: false,
|
||||
|
@ -135,10 +182,11 @@ type BaseConfigContext = {|
|
|||
dev: boolean,
|
||||
isServer: boolean,
|
||||
buildId: string,
|
||||
config: NextConfig
|
||||
config: NextConfig,
|
||||
lambdas: boolean
|
||||
|}
|
||||
|
||||
export default async function getBaseWebpackConfig (dir: string, {dev = false, isServer = false, buildId, config}: BaseConfigContext) {
|
||||
export default async function getBaseWebpackConfig (dir: string, {dev = false, isServer = false, buildId, config, lambdas = false}: BaseConfigContext) {
|
||||
const defaultLoaders = {
|
||||
babel: {
|
||||
loader: 'next-babel-loader',
|
||||
|
@ -194,8 +242,8 @@ export default async function getBaseWebpackConfig (dir: string, {dev = false, i
|
|||
name: isServer ? 'server' : 'client',
|
||||
cache: true,
|
||||
target: isServer ? 'node' : 'web',
|
||||
externals: externalsConfig(dir, isServer),
|
||||
optimization: optimizationConfig({dir, dev, isServer, totalPages}),
|
||||
externals: externalsConfig(dir, isServer, lambdas),
|
||||
optimization: optimizationConfig({dir, dev, isServer, totalPages, lambdas}),
|
||||
recordsPath: path.join(outputPath, 'records.json'),
|
||||
context: dir,
|
||||
// Kept as function to be backwards compatible
|
||||
|
|
7
test/integration/lambdas/next.config.js
Normal file
7
test/integration/lambdas/next.config.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
module.exports = {
|
||||
onDemandEntries: {
|
||||
// Make sure entries are not getting disposed.
|
||||
maxInactiveAge: 1000 * 60 * 60
|
||||
},
|
||||
lambdas: true
|
||||
}
|
1
test/integration/lambdas/pages/index.js
Normal file
1
test/integration/lambdas/pages/index.js
Normal file
|
@ -0,0 +1 @@
|
|||
export default () => 'Hello World'
|
38
test/integration/lambdas/test/index.test.js
Normal file
38
test/integration/lambdas/test/index.test.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* eslint-env jest */
|
||||
/* global jasmine, test */
|
||||
import { join } from 'path'
|
||||
import {
|
||||
nextServer,
|
||||
nextBuild,
|
||||
startApp,
|
||||
stopApp,
|
||||
renderViaHTTP
|
||||
} from 'next-test-utils'
|
||||
|
||||
const appDir = join(__dirname, '../')
|
||||
let appPort
|
||||
let server
|
||||
let app
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5
|
||||
|
||||
const context = {}
|
||||
|
||||
describe('Lambdas', () => {
|
||||
beforeAll(async () => {
|
||||
await nextBuild(appDir)
|
||||
app = nextServer({
|
||||
dir: join(__dirname, '../'),
|
||||
dev: false,
|
||||
quiet: true
|
||||
})
|
||||
|
||||
server = await startApp(app)
|
||||
context.appPort = appPort = server.address().port
|
||||
})
|
||||
afterAll(() => stopApp(server))
|
||||
|
||||
it('should render the page', async () => {
|
||||
const html = await renderViaHTTP(appPort, '/')
|
||||
expect(html).toMatch(/Hello World/)
|
||||
})
|
||||
})
|
Loading…
Reference in a new issue