Skip to content

fix: handle Windows paths correctly #948

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

Merged
merged 3 commits into from
Dec 10, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/helpers/cache.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { posix } from 'path'
import { join } from 'path'

export const restoreCache = async ({ cache, publish }) => {
const cacheDir = posix.join(publish, 'cache')
const cacheDir = join(publish, 'cache')

if (await cache.restore(cacheDir)) {
console.log('Next.js cache restored.')
Expand All @@ -11,9 +11,9 @@ export const restoreCache = async ({ cache, publish }) => {
}

export const saveCache = async ({ cache, publish }) => {
const cacheDir = posix.join(publish, 'cache')
const cacheDir = join(publish, 'cache')

const buildManifest = posix.join(publish, 'build-manifest.json')
const buildManifest = join(publish, 'build-manifest.json')
if (await cache.save(cacheDir, { digests: [buildManifest] })) {
console.log('Next.js cache saved.')
} else {
Expand Down
6 changes: 2 additions & 4 deletions src/helpers/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,16 @@ export const generateFunctions = async (
* This is just so that the nft bundler knows about them. We'll eventually do this better.
*/
export const generatePagesResolver = async ({
constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC },
netlifyConfig,
constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC, PUBLISH_DIR },
target,
}: {
constants: NetlifyPluginConstants
netlifyConfig: NetlifyConfig
target: string
}): Promise<void> => {
const functionsPath = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC

const jsSource = await getPageResolver({
netlifyConfig,
publish: PUBLISH_DIR,
target,
})

Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const plugin: NetlifyPlugin = {
configureHandlerFunctions({ netlifyConfig, ignore, publish: relative(process.cwd(), publish) })

await generateFunctions(constants, appDir)
await generatePagesResolver({ netlifyConfig, target, constants })
await generatePagesResolver({ target, constants })

await movePublicFiles({ appDir, outdir, publish })

Expand Down
4 changes: 2 additions & 2 deletions src/templates/getPageResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { HANDLER_FUNCTION_NAME } from '../constants'
// Generate a file full of require.resolve() calls for all the pages in the
// build. This is used by the nft bundler to find all the pages.

export const getPageResolver = async ({ netlifyConfig, target }) => {
export const getPageResolver = async ({ publish, target }: { publish: string; target: string }) => {
const functionDir = posix.resolve(posix.join('.netlify', 'functions', HANDLER_FUNCTION_NAME))
const root = posix.join(netlifyConfig.build.publish, target === 'server' ? 'server' : 'serverless', 'pages')
const root = posix.resolve(slash(publish), target === 'server' ? 'server' : 'serverless', 'pages')

const pages = await glob('**/*.js', {
cwd: root,
Expand Down
70 changes: 70 additions & 0 deletions test/__snapshots__/index.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,76 @@ exports.resolvePages = () => {
}"
`;

exports[`onBuild() generates a file referencing all when publish dir is a subdirectory 1`] = `
"// This file is purely to allow nft to know about these pages. It should be temporary.
exports.resolvePages = () => {
try {
require.resolve('../../../web/.next/server/pages/_app.js')
require.resolve('../../../web/.next/server/pages/_document.js')
require.resolve('../../../web/.next/server/pages/_error.js')
require.resolve('../../../web/.next/server/pages/api/enterPreview.js')
require.resolve('../../../web/.next/server/pages/api/exitPreview.js')
require.resolve('../../../web/.next/server/pages/api/hello-background.js')
require.resolve('../../../web/.next/server/pages/api/hello.js')
require.resolve('../../../web/.next/server/pages/api/shows/[...params].js')
require.resolve('../../../web/.next/server/pages/api/shows/[id].js')
require.resolve('../../../web/.next/server/pages/deep/import.js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/[id].js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/all/[[...slug]].js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/static.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/env.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/static.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/with-revalidate.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withFallback/[...slug].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withFallback/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withFallbackBlocking/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withRevalidate/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withRevalidate/withFallback/[id].js')
require.resolve('../../../web/.next/server/pages/index.js')
require.resolve('../../../web/.next/server/pages/middle/_middleware.js')
require.resolve('../../../web/.next/server/pages/previewTest.js')
require.resolve('../../../web/.next/server/pages/shows/[...params].js')
require.resolve('../../../web/.next/server/pages/shows/[id].js')
} catch {}
}"
`;

exports[`onBuild() generates a file referencing all when publish dir is a subdirectory 2`] = `
"// This file is purely to allow nft to know about these pages. It should be temporary.
exports.resolvePages = () => {
try {
require.resolve('../../../web/.next/server/pages/_app.js')
require.resolve('../../../web/.next/server/pages/_document.js')
require.resolve('../../../web/.next/server/pages/_error.js')
require.resolve('../../../web/.next/server/pages/api/enterPreview.js')
require.resolve('../../../web/.next/server/pages/api/exitPreview.js')
require.resolve('../../../web/.next/server/pages/api/hello-background.js')
require.resolve('../../../web/.next/server/pages/api/hello.js')
require.resolve('../../../web/.next/server/pages/api/shows/[...params].js')
require.resolve('../../../web/.next/server/pages/api/shows/[id].js')
require.resolve('../../../web/.next/server/pages/deep/import.js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/[id].js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/all/[[...slug]].js')
require.resolve('../../../web/.next/server/pages/getServerSideProps/static.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/env.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/static.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/with-revalidate.js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withFallback/[...slug].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withFallback/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withFallbackBlocking/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withRevalidate/[id].js')
require.resolve('../../../web/.next/server/pages/getStaticProps/withRevalidate/withFallback/[id].js')
require.resolve('../../../web/.next/server/pages/index.js')
require.resolve('../../../web/.next/server/pages/middle/_middleware.js')
require.resolve('../../../web/.next/server/pages/previewTest.js')
require.resolve('../../../web/.next/server/pages/shows/[...params].js')
require.resolve('../../../web/.next/server/pages/shows/[id].js')
} catch {}
}"
`;

exports[`onBuild() generates static files manifest 1`] = `
Array [
Array [
Expand Down
37 changes: 28 additions & 9 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const plugin = require('../src')
const { HANDLER_FUNCTION_NAME, ODB_FUNCTION_NAME } = require('../src/constants')
const { join } = require('pathe')
const { matchMiddleware, stripLocale, matchesRedirect, matchesRewrite } = require('../src/helpers/files')
const { dirname } = require('path')

const FIXTURES_DIR = `${__dirname}/fixtures`
const SAMPLE_PROJECT_DIR = `${__dirname}/../demos/default`
Expand Down Expand Up @@ -83,19 +84,20 @@ const changeCwd = function (cwd) {
const onBuildHasRun = (netlifyConfig) =>
Boolean(netlifyConfig.functions[HANDLER_FUNCTION_NAME]?.included_files?.some((file) => file.includes('BUILD_ID')))

const rewriteAppDir = async function () {
const manifest = path.join('.next', 'required-server-files.json')
const rewriteAppDir = async function (dir = '.next') {
const manifest = path.join(dir, 'required-server-files.json')
const manifestContent = await readJson(manifest)
manifestContent.appDir = process.cwd()

await writeJSON(manifest, manifestContent)
}

// Move .next from sample project to current directory
const moveNextDist = async function () {
const moveNextDist = async function (dir = '.next') {
await stubModules(['next', 'sharp'])
await copy(path.join(SAMPLE_PROJECT_DIR, '.next'), path.join(process.cwd(), '.next'))
await rewriteAppDir()
await ensureDir(dirname(dir))
await copy(path.join(SAMPLE_PROJECT_DIR, '.next'), path.join(process.cwd(), dir))
await rewriteAppDir(dir)
}

const stubModules = async function (modules) {
Expand Down Expand Up @@ -129,7 +131,7 @@ beforeEach(async () => {
restoreCwd = changeCwd(tmpDir.path)
cleanup = tmpDir.cleanup

netlifyConfig.build.publish = path.posix.resolve('.next')
netlifyConfig.build.publish = path.resolve('.next')
netlifyConfig.build.environment = {}

netlifyConfig.redirects = []
Expand Down Expand Up @@ -183,7 +185,7 @@ describe('preBuild()', () => {
utils: { ...utils, cache: { restore } },
})

expect(restore).toHaveBeenCalledWith(path.posix.resolve('.next/cache'))
expect(restore).toHaveBeenCalledWith(path.resolve('.next/cache'))
})

it('forces the target to "server"', async () => {
Expand Down Expand Up @@ -337,6 +339,23 @@ describe('onBuild()', () => {
expect(readFileSync(odbHandlerPagesFile, 'utf8')).toMatchSnapshot()
})

test('generates a file referencing all when publish dir is a subdirectory', async () => {
const dir = 'web/.next'
await moveNextDist(dir)
netlifyConfig.build.publish = path.resolve(dir)
const config = {
...defaultArgs,
netlifyConfig,
constants: { ...constants, PUBLISH_DIR: dir },
}
await plugin.onBuild(config)
const handlerPagesFile = path.join(constants.INTERNAL_FUNCTIONS_SRC, HANDLER_FUNCTION_NAME, 'pages.js')
const odbHandlerPagesFile = path.join(constants.INTERNAL_FUNCTIONS_SRC, ODB_FUNCTION_NAME, 'pages.js')

expect(readFileSync(handlerPagesFile, 'utf8')).toMatchSnapshot()
expect(readFileSync(odbHandlerPagesFile, 'utf8')).toMatchSnapshot()
})

test('generates entrypoints with correct references', async () => {
await moveNextDist()
await plugin.onBuild(defaultArgs)
Expand Down Expand Up @@ -368,8 +387,8 @@ describe('onPostBuild', () => {
utils: { ...utils, cache: { save }, functions: { list: jest.fn().mockResolvedValue([]) } },
})

expect(save).toHaveBeenCalledWith(path.posix.resolve('.next/cache'), {
digests: [path.posix.resolve('.next/build-manifest.json')],
expect(save).toHaveBeenCalledWith(path.resolve('.next/cache'), {
digests: [path.resolve('.next/build-manifest.json')],
})
})

Expand Down