Skip to content
This repository has been archived by the owner on May 22, 2024. It is now read-only.

Commit

Permalink
refator: tree shake next when next-on-netlify is used
Browse files Browse the repository at this point in the history
  • Loading branch information
erezrokah committed Dec 16, 2020
1 parent 2692041 commit dd6a238
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 40 deletions.
56 changes: 18 additions & 38 deletions src/dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const getPackageJson = function(packageRoot) {
}
}

const getFileDependencies = async function({ path, packageJson, state, treeShakingModule }) {
const getFileDependencies = async function({ path, packageJson, state, treeShakeNext }) {
if (state.localFiles.has(path)) {
return []
}
Expand All @@ -84,58 +84,38 @@ const getFileDependencies = async function({ path, packageJson, state, treeShaki
const dependencies = precinct.paperwork(path, { includeCore: false })

const depsPaths = await Promise.all(
dependencies.map(dependency =>
getImportDependencies({ dependency, basedir, packageJson, state, treeShakingModule })
)
dependencies.map(dependency => getImportDependencies({ dependency, basedir, packageJson, state, treeShakeNext }))
)
return [].concat(...depsPaths)
}

const isTreeShakingModule = function(moduleName, treeShakingModule) {
return moduleName === treeShakingModule
}

const getImportDependencies = function({ dependency, basedir, packageJson, state, treeShakingModule }) {
const moduleName = getModuleName(dependency)
const isLocalImport = LOCAL_IMPORT_REGEXP.test(dependency)
if (isLocalImport || isTreeShakingModule(moduleName, treeShakingModule) || isTreeShakable(dependency)) {
const treeShakingState = isLocalImport ? { treeShakingModule } : { treeShakingModule: moduleName }
return getTreeShakedDependencies({ dependency, basedir, packageJson, state, ...treeShakingState })
const getImportDependencies = function({ dependency, basedir, packageJson, state, treeShakeNext }) {
const shouldTreeShakeNext = treeShakeNext || isNextOnNetlify(dependency)
if (shouldTreeShake(dependency, shouldTreeShakeNext)) {
return getTreeShakedDependencies({ dependency, basedir, packageJson, state, treeShakeNext: shouldTreeShakeNext })
}

return getAllDependencies({ dependency, basedir, state, packageJson })
}

const LOCAL_IMPORT_REGEXP = /^(\.|\/)/
const isNextOnNetlify = function(dependency) {
return dependency === './renderNextPage'
}

const shouldTreeShake = function(dependency, treeShakeNext) {
if (LOCAL_IMPORT_REGEXP.test(dependency)) {
return true
}

const isTreeShakable = function(dependency) {
return TREE_SHAKABLE_DEPENDENCIES.has(dependency)
return treeShakeNext && getModuleName(dependency) === 'next'
}

const TREE_SHAKABLE_DEPENDENCIES = new Set([
'next/dist/next-server/lib/constants',
'next/dist/next-server/lib/constants.js',
'next/dist/next-server/lib/document-context.js',
'next/dist/next-server/lib/head.js',
'next/dist/next-server/lib/i18n/normalize-locale-path',
'next/dist/next-server/lib/router/utils/get-route-from-asset-path',
'next/dist/next-server/lib/router/utils/path-match',
'next/dist/next-server/lib/router/utils/prepare-destination',
'next/dist/next-server/lib/utils',
'next/dist/next-server/lib/utils.js',
'next/dist/next-server/server/api-utils',
'next/dist/next-server/server/denormalize-page-path',
'next/dist/next-server/server/get-page-files.js',
'next/dist/next-server/server/node-polyfill-fetch',
'next/dist/next-server/server/render',
'next/dist/next-server/server/send-payload',
'next/dist/next-server/server/utils.js'
])
const LOCAL_IMPORT_REGEXP = /^(\.|\/)/

// When a file requires another one, we apply the top-level logic recursively
const getTreeShakedDependencies = async function({ dependency, basedir, packageJson, state, treeShakingModule }) {
const getTreeShakedDependencies = async function({ dependency, basedir, packageJson, state, treeShakeNext }) {
const path = await resolvePathPreserveSymlinks(dependency, basedir)
const depsPath = await getFileDependencies({ path, packageJson, state, treeShakingModule })
const depsPath = await getFileDependencies({ path, packageJson, state, treeShakeNext })
return [path, ...depsPath]
}

Expand Down
3 changes: 3 additions & 0 deletions src/fixtures/node-module-next-on-netlify/function/function.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require('./renderNextPage')

module.exports = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// eslint-disable-next-line node/no-extraneous-require
require('next/dist/next-server/lib/constants')

module.exports = true

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 16 additions & 2 deletions src/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ test('Include most files from node modules', async t => {
t.true(htmlExists)
})

test('Include specific Next.js dependencies', async t => {
const { tmpDir } = await zipNode(t, 'node-module-next')
test('Includes specific Next.js dependencies when using next-on-netlify', async t => {
const { tmpDir } = await zipNode(t, 'node-module-next-on-netlify')
const [constantsExists, semverExists, otherExists, indexExists] = await Promise.all([
pathExists(`${tmpDir}/src/node_modules/next/dist/next-server/lib/constants.js`),
pathExists(`${tmpDir}/src/node_modules/next/dist/compiled/semver.js`),
Expand All @@ -85,6 +85,20 @@ test('Include specific Next.js dependencies', async t => {
t.false(indexExists)
})

test('Includes all Next.js dependencies when not using next-on-netlify', async t => {
const { tmpDir } = await zipNode(t, 'node-module-next')
const [constantsExists, semverExists, otherExists, indexExists] = await Promise.all([
pathExists(`${tmpDir}/src/node_modules/next/dist/next-server/lib/constants.js`),
pathExists(`${tmpDir}/src/node_modules/next/dist/compiled/semver.js`),
pathExists(`${tmpDir}/src/node_modules/next/dist/other.js`),
pathExists(`${tmpDir}/src/node_modules/next/index.js`)
])
t.true(constantsExists)
t.true(semverExists)
t.true(otherExists)
t.true(indexExists)
})

test('Throws on runtime errors', async t => {
await t.throwsAsync(zipNode(t, 'node-module-error'))
})
Expand Down

0 comments on commit dd6a238

Please sign in to comment.