Skip to content

fix: copy public directory output instead of input when using Nx #856

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 6, 2021
Merged

fix: copy public directory output instead of input when using Nx #856

merged 3 commits into from
Dec 6, 2021

Conversation

lourd
Copy link

@lourd lourd commented Nov 30, 2021

Summary

When copying the public directory, the build plugin should use the one that Next.js generates as part of the build, not the input one, as there may be files added to the directory as part of the build process. For example, using the InjectManifest plugin from workbox-webpack-plugin like this to produce the specifically named and located file service-worker.js:

// next.config.js
module.exports = {
  webpack: (config, options) => {
    if (!options.dev) {
      const workboxManifestPlugin = new InjectManifest({
        swSrc: "./src/service-worker.ts",
        swDest: "../public/service-worker.js",
      })
      config.plugins.push(workboxManifestPlugin)
    }
  }
}

Test plan

Added a test to the Nx cypress setup. Steps to run:

cd demos/nx-next-monorepo-demo
npm install
npm run build
npx nx run demo-monorepo:serve:production --port=3000

Then in a separate terminal, from the repo root

npm run cy:open

Then click the general.spec.ts. under the nx folder to run it.

Relevant links (GitHub issues, Notion docs, etc.) or a picture of cute animal

IMG_2478

Standard checks:

  • Check the Deploy Preview's Demo site for your PR's functionality
  • Add docs when necessary

@opennextjs opennextjs deleted a comment from netlify bot Nov 30, 2021
@tiffafoo tiffafoo added the type: bug code to address defects in shipped code label Nov 30, 2021
src/index.js Outdated
@@ -47,14 +47,14 @@ module.exports = {

checkNextSiteHasBuilt({ publish, failBuild })

const { appDir, basePath, i18n, images, target, ignore } = await getNextConfig({ publish, failBuild })
const { appDir, basePath, i18n, images, target, ignore, outdir } = await getNextConfig({ publish, failBuild })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain where you're getting this config name? I'm not aware of outdir being a standard config value.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's added when you're using Next.js with Nx. You can see the source code adding it here

@ascorbic
Copy link
Contributor

The public dir is used as-is, not generated by Next. It's just meant to be used for static files. If you want to generate other files you should be creating them in .next. Are you referring to somethign else?

@lourd
Copy link
Author

lourd commented Nov 30, 2021

Ah, looks like this is a difference when using Next with Nx. Nx copies the public directory over to the specified output directory, where it also puts the .next directory. I just tried a project started with create-next-app and it doesn't have config.outdir in required-server-files.json, and it doesn't create a new public directory, even when specifying an alternative distDir.

The issue with putting generated files in the generated static directory is that they're then served from /static or /_next/static. Some files need to served from root — for example, the /.well-known/apple-app-site-association that makes deep linking work on iOS. And some of those files get modified or created at build time. What's a good way to go about that with vanilla Next.js, without Nx?

Would you support updating the PR to conditionally use/join outdir to appDir if it exists, to support this Nx-specific case?

@tiffafoo tiffafoo added the status: needs reproduction this issue needs to provide a repo that reproduces the bug described label Nov 30, 2021
@lourd
Copy link
Author

lourd commented Nov 30, 2021

I went ahead and made it conditional with a comment explaining the case. I also made a Nx workspace with a Next.js project to demonstrate -- https://github.com/lourd/nx-next-public-example. To see what I'm talking about, clone it and run yarn build. It will generate a directory at dist/apps/next-public-test which as the .next directory, a public directory, and next.config.js. If you look in the required-server-files.json you'll see the outdir property with a value of "../../dist/apps/next-public-test". And the public directory has the files that were in public to start with (star.svg, nx-log-white.svg) as well as the service-worker.js file that was specified added by the InjectManifest plugin as specified in the webpack setup in next.config.js.

If you want, you can also run the build to see the service worker getting registered and loaded from that public location. The command for that is yarn nx run next-public-test:serve:production. You'll only see the service worker logs the first time the page loads — to see it on subsequent loads you need to unregister it through the browser's dev tools.

@lourd
Copy link
Author

lourd commented Nov 30, 2021

I also just added a test to the Cypress suite for nx-next-monorepo-demo. Updated the test plan in the PR description with steps to run it. Please let me know if there's anything else I can do!

@lourd lourd changed the title fix: copy public directory output instead of input fix: copy public directory output instead of input when using Nx Nov 30, 2021
@lourd lourd requested a review from ascorbic November 30, 2021 20:20
@tiffafoo tiffafoo removed the status: needs reproduction this issue needs to provide a repo that reproduces the bug described label Dec 1, 2021
@netlify
Copy link

netlify bot commented Dec 1, 2021

‼️ Deploy request for netlify-plugin-nextjs-static-root-demo rejected.
Learn more about Netlify's sensitive variable policy

🔨 Explore the source changes: 49c5147

@ascorbic ascorbic assigned tiffafoo and unassigned ascorbic Dec 3, 2021

it('serves generated public files', () => {
cy.request(`service-worker.js`)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can be more explicit with the assetion here by making sure the status returned is a 200. Something like this:

Suggested change
cy.request(`service-worker.js`)
cy.request('service-worker.js').then((res) => {
expect(res.status).to.eq(200)
})

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 went ahead and added that and a check for the content-type (in case it's serving some fallback html instead of js!)

tiffafoo
tiffafoo previously approved these changes Dec 3, 2021
Copy link

@tiffafoo tiffafoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the test steps, comments and taking the time to explain the nx use case, super appreciated! I tested using your test steps with and without the outdir as well as using netlify deploy --build and things seem to be behaving as expected 🎉 .

@lourd
Copy link
Author

lourd commented Dec 3, 2021

😃 For sure! Please let me know if there's anything else this needs to be merged.

@kodiakhq kodiakhq bot removed the automerge label Dec 6, 2021
@kodiakhq
Copy link
Contributor

kodiakhq bot commented Dec 6, 2021

This PR currently has a merge conflict. Please resolve this and then re-add the automerge label.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge type: bug code to address defects in shipped code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants