From 854a84937c20cd31ad06795c5660234cf486419f Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 12 Oct 2020 05:05:47 -0500 Subject: [PATCH 1/5] Fix a couple i18n cases (#17805) While working on https://github.com/vercel/next.js/pull/17755 noticed a couple of cases that needed fixing and broke them out to this PR to make that one easier to review. One fix is for `ssgCacheKey` where it wasn't having the `locale` prefix stripped correctly due to the locales no longer being populated under the server instances `renderOpts` and the second fix is for the `asPath` not being set to `/` when the `locale` is the only part in the URL e.g. `/en` became an empty string `""` x-ref: https://github.com/vercel/next.js/pull/17370 --- packages/next/client/index.tsx | 2 +- .../next/next-server/server/next-server.ts | 16 +++---- .../i18n-support/test/index.test.js | 43 ++++++++++++++++++- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/packages/next/client/index.tsx b/packages/next/client/index.tsx index 22e926dd8c73..a7a4b069f7b2 100644 --- a/packages/next/client/index.tsx +++ b/packages/next/client/index.tsx @@ -92,7 +92,7 @@ if (process.env.__NEXT_i18n_SUPPORT) { const localePathResult = normalizeLocalePath(asPath, locales) if (localePathResult.detectedLocale) { - asPath = asPath.substr(localePathResult.detectedLocale.length + 1) + asPath = asPath.substr(localePathResult.detectedLocale.length + 1) || '/' } else { // derive the default locale if it wasn't detected in the asPath // since we don't prerender static pages with all possible default diff --git a/packages/next/next-server/server/next-server.ts b/packages/next/next-server/server/next-server.ts index 1afeba5ce1f0..69a4b75f00f0 100644 --- a/packages/next/next-server/server/next-server.ts +++ b/packages/next/next-server/server/next-server.ts @@ -1150,6 +1150,13 @@ export default class Server { const isDataReq = !!query._nextDataReq && (isSSG || isServerProps) delete query._nextDataReq + const locale = query.__nextLocale as string + const locales = query.__nextLocales as string[] + // const defaultLocale = query.__nextDefaultLocale as string + delete query.__nextLocale + delete query.__nextLocales + // delete query.__nextDefaultLocale + let previewData: string | false | object | undefined let isPreviewMode = false @@ -1178,7 +1185,7 @@ export default class Server { } if (this.nextConfig.experimental.i18n) { - return normalizeLocalePath(path, this.renderOpts.locales).pathname + return normalizeLocalePath(path, locales).pathname } return path } @@ -1190,13 +1197,6 @@ export default class Server { urlPathname = stripNextDataPath(urlPathname) } - const locale = query.__nextLocale as string - const locales = query.__nextLocales as string[] - // const defaultLocale = query.__nextDefaultLocale as string - delete query.__nextLocale - delete query.__nextLocales - // delete query.__nextDefaultLocale - const ssgCacheKey = isPreviewMode || !isSSG ? undefined // Preview mode bypasses the cache diff --git a/test/integration/i18n-support/test/index.test.js b/test/integration/i18n-support/test/index.test.js index 429be47a832b..f0cd92b4da62 100644 --- a/test/integration/i18n-support/test/index.test.js +++ b/test/integration/i18n-support/test/index.test.js @@ -26,7 +26,46 @@ let appPort const locales = ['en-US', 'nl-NL', 'nl-BE', 'nl', 'fr-BE', 'fr', 'en'] -function runTests() { +function runTests(isDev) { + it('should update asPath on the client correctly', async () => { + for (const check of ['en', 'En']) { + const browser = await webdriver(appPort, `/${check}`) + + expect(await browser.elementByCss('html').getAttribute('lang')).toBe('en') + expect(await browser.elementByCss('#router-locale').text()).toBe('en') + expect( + JSON.parse(await browser.elementByCss('#router-locales').text()) + ).toEqual(locales) + expect(await browser.elementByCss('#router-as-path').text()).toBe('/') + expect(await browser.elementByCss('#router-pathname').text()).toBe('/') + } + }) + + if (!isDev) { + it('should handle fallback correctly after generating', async () => { + const browser = await webdriver( + appPort, + '/en/gsp/fallback/hello-fallback' + ) + + // wait for the fallback to be generated/stored to ISR cache + browser.waitForElementByCss('#gsp') + + // now make sure we're serving the previously generated file from the cache + const html = await renderViaHTTP( + appPort, + '/en/gsp/fallback/hello-fallback' + ) + const $ = cheerio.load(html) + + expect($('#gsp').text()).toBe('gsp page') + expect($('#router-locale').text()).toBe('en') + expect(JSON.parse($('#router-locales').text())).toEqual(locales) + expect($('#router-pathname').text()).toBe('/gsp/fallback/[slug]') + expect($('#router-as-path').text()).toBe('/gsp/fallback/hello-fallback') + }) + } + it('should use correct default locale for locale domains', async () => { const res = await fetchViaHTTP(appPort, '/', undefined, { headers: { @@ -729,7 +768,7 @@ describe('i18n Support', () => { }) afterAll(() => killApp(app)) - runTests() + runTests(true) }) describe('production mode', () => { From 1c4aecbeaf9de44cec3484f76d23ec8103f3bc50 Mon Sep 17 00:00:00 2001 From: Henrik Wenz Date: Mon, 12 Oct 2020 18:37:56 +0200 Subject: [PATCH 2/5] Improve with-tailwindcss example (#17742) ## Change To opt-in to using the new layers mode by default. ## Motivation - Reduces CSS filesize - Prevents users from using the already deprecated old layers mode - Removes the following console warnings: ```log risk - There are upcoming breaking changes: purgeLayersByDefault risk - We highly recommend opting-in to these changes now to simplify upgrading Tailwind in the future. risk - https://tailwindcss.com/docs/upcoming-changes ``` [more info](https://tailwindcss.com/docs/upcoming-changes) --- examples/with-tailwindcss/tailwind.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/with-tailwindcss/tailwind.config.js b/examples/with-tailwindcss/tailwind.config.js index 544a211e989e..65167cc61c36 100644 --- a/examples/with-tailwindcss/tailwind.config.js +++ b/examples/with-tailwindcss/tailwind.config.js @@ -1,6 +1,7 @@ module.exports = { future: { removeDeprecatedGapUtilities: true, + purgeLayersByDefault: true, }, purge: ['./components/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}'], theme: { From 71d798ce889932311f2ef575c4c80b09ad57bb6f Mon Sep 17 00:00:00 2001 From: Prateek Bhatnagar Date: Mon, 12 Oct 2020 11:58:09 -0700 Subject: [PATCH 3/5] Font optimization for webpack 5 (#17450) Co-authored-by: Tim Neutkens Co-authored-by: Tim Neutkens --- .github/workflows/build_test_deploy.yml | 7 +++-- .../font-stylesheet-gathering-plugin.ts | 30 +++++++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build_test_deploy.yml b/.github/workflows/build_test_deploy.yml index 2ce0e8e95fa1..5bc2f97e2b5b 100644 --- a/.github/workflows/build_test_deploy.yml +++ b/.github/workflows/build_test_deploy.yml @@ -107,12 +107,13 @@ jobs: steps: - uses: actions/checkout@v2 - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - - run: cat package.json | jq '.resolutions.webpack = "^5.0.0-beta.30"' > package.json.tmp && mv package.json.tmp package.json - - run: cat package.json | jq '.resolutions.react = "^17.0.0-rc.1"' > package.json.tmp && mv package.json.tmp package.json - - run: cat package.json | jq '.resolutions."react-dom" = "^17.0.0-rc.1"' > package.json.tmp && mv package.json.tmp package.json + - run: cat packages/next/package.json | jq '.resolutions.webpack = "^5.0.0-beta.30"' > package.json.tmp && mv package.json.tmp packages/next/package.json + - run: cat packages/next/package.json | jq '.resolutions.react = "^17.0.0-rc.1"' > package.json.tmp && mv package.json.tmp packages/next/package.json + - run: cat packages/next/package.json | jq '.resolutions."react-dom" = "^17.0.0-rc.1"' > package.json.tmp && mv package.json.tmp packages/next/package.json - run: yarn install --check-files - run: node run-tests.js test/integration/production/test/index.test.js - run: node run-tests.js test/integration/basic/test/index.test.js + - run: node run-tests.js test/integration/font-optimization/test/index.test.js - run: node run-tests.js test/acceptance/* testFirefox: diff --git a/packages/next/build/webpack/plugins/font-stylesheet-gathering-plugin.ts b/packages/next/build/webpack/plugins/font-stylesheet-gathering-plugin.ts index 5b8517cf0cff..3a8763f97b54 100644 --- a/packages/next/build/webpack/plugins/font-stylesheet-gathering-plugin.ts +++ b/packages/next/build/webpack/plugins/font-stylesheet-gathering-plugin.ts @@ -5,8 +5,6 @@ import { getFontDefinitionFromNetwork, FontManifest, } from '../../../next-server/server/font-utils' -// @ts-ignore -import BasicEvaluatedExpression from 'webpack/lib/BasicEvaluatedExpression' import postcss from 'postcss' import minifier from 'cssnano-simple' import { OPTIMIZED_FONT_PROVIDERS } from '../../../next-server/lib/constants' @@ -16,6 +14,13 @@ const { RawSource } = webpack.sources || sources const isWebpack5 = parseInt(webpack.version!) === 5 +let BasicEvaluatedExpression: any +if (isWebpack5) { + BasicEvaluatedExpression = require('webpack/lib/javascript/BasicEvaluatedExpression') +} else { + BasicEvaluatedExpression = require('webpack/lib/BasicEvaluatedExpression') +} + async function minifyCss(css: string): Promise { return new Promise((resolve) => postcss([ @@ -62,13 +67,20 @@ export class FontStylesheetGatheringPlugin { if (parser?.state?.module?.resource.includes('node_modules')) { return } - return node.name === '__jsx' - ? new BasicEvaluatedExpression() - //@ts-ignore - .setRange(node.range) - .setExpression(node) - .setIdentifier('__jsx') - : undefined + let result + if (node.name === '__jsx') { + result = new BasicEvaluatedExpression() + // @ts-ignore + result.setRange(node.range) + result.setExpression(node) + result.setIdentifier('__jsx') + + // This was added webpack 5. + if (isWebpack5) { + result.getMembers = () => [] + } + } + return result }) parser.hooks.call From d73b34c3fd4008d3a8a175ad52310c83c1e5c8a4 Mon Sep 17 00:00:00 2001 From: Amir Ali <43801058+amirsaeed671@users.noreply.github.com> Date: Tue, 13 Oct 2020 23:55:21 +0500 Subject: [PATCH 4/5] Fix higherOrderComponent causing broken layout (#17812) `higherOrderComponent(WrappedComponent)` causing the layout broken in mobile screen. * refer to screenshots below. ![image](https://user-images.githubusercontent.com/43801058/95730641-faaa6c80-0c97-11eb-9951-2a47b61cefad.png) ![image](https://user-images.githubusercontent.com/43801058/95730661-0138e400-0c98-11eb-9f02-b4d0676fd21b.png) if we could make it `HOC(WrappedComponent)` it will not break the layout in mobile screen ![image](https://user-images.githubusercontent.com/43801058/95730673-04cc6b00-0c98-11eb-8782-2fa1f760f8fd.png) --- docs/basic-features/fast-refresh.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/basic-features/fast-refresh.md b/docs/basic-features/fast-refresh.md index 450b19e6db4b..162625d2934b 100644 --- a/docs/basic-features/fast-refresh.md +++ b/docs/basic-features/fast-refresh.md @@ -75,7 +75,7 @@ local state being reset on every edit to a file: - The file you're editing might have _other_ exports in addition to a React component. - Sometimes, a file would export the result of calling higher-order component - like `higherOrderComponent(WrappedComponent)`. If the returned component is a + like `HOC(WrappedComponent)`. If the returned component is a class, state will be reset. As more of your codebase moves to function components and Hooks, you can expect From f1b3818dadab089c9c4faaa2695372c9e07e2c96 Mon Sep 17 00:00:00 2001 From: GP Date: Wed, 14 Oct 2020 00:47:47 +0530 Subject: [PATCH 5/5] docs: Clarify use of getStaticProps / getServerSideProps with app / document (#17839) Fixes https://github.com/vercel/next.js/issues/17828. This change adds a caveat to both the "Custom `App`" and "Custom `Document`" pages about how both `getStaticProps` and `getServerSideProps` aren't supported. --- docs/advanced-features/custom-app.md | 1 + docs/advanced-features/custom-document.md | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/advanced-features/custom-app.md b/docs/advanced-features/custom-app.md index 8f0ea8aab405..571bf79da5a6 100644 --- a/docs/advanced-features/custom-app.md +++ b/docs/advanced-features/custom-app.md @@ -44,6 +44,7 @@ The `Component` prop is the active `page`, so whenever you navigate between rout - If your app is running and you just added a custom `App`, you'll need to restart the development server. Only required if `pages/_app.js` didn't exist before. - Adding a custom `getInitialProps` in your `App` will disable [Automatic Static Optimization](/docs/advanced-features/automatic-static-optimization.md) in pages without [Static Generation](/docs/basic-features/data-fetching.md#getstaticprops-static-generation). +- `App` currently does not support Next.js [Data Fetching methods](/docs/basic-features/data-fetching.md) like [`getStaticProps`](/docs/basic-features/data-fetching.md#getstaticprops-static-generation) or [`getServerSideProps`](/docs/basic-features/data-fetching.md#getserversideprops-server-side-rendering). ### TypeScript diff --git a/docs/advanced-features/custom-document.md b/docs/advanced-features/custom-document.md index 363ff1215f43..2c75cca86b37 100644 --- a/docs/advanced-features/custom-document.md +++ b/docs/advanced-features/custom-document.md @@ -51,9 +51,10 @@ The `ctx` object is equivalent to the one received in [`getInitialProps`](/docs/ ## Caveats -- `Document` is only rendered in the server, event handlers like `onClick` won't work -- React components outside of `
` will not be initialized by the browser. Do _not_ add application logic here or custom CSS (like `styled-jsx`). If you need shared components in all your pages (like a menu or a toolbar), take a look at the [`App`](/docs/advanced-features/custom-app.md) component instead -- `Document`'s `getInitialProps` function is not called during client-side transitions, nor when a page is [statically optimized](/docs/advanced-features/automatic-static-optimization.md) +- `Document` is only rendered in the server, event handlers like `onClick` won't work. +- React components outside of `
` will not be initialized by the browser. Do _not_ add application logic here or custom CSS (like `styled-jsx`). If you need shared components in all your pages (like a menu or a toolbar), take a look at the [`App`](/docs/advanced-features/custom-app.md) component instead. +- `Document`'s `getInitialProps` function is not called during client-side transitions, nor when a page is [statically optimized](/docs/advanced-features/automatic-static-optimization.md). +- `Document` currently does not support Next.js [Data Fetching methods](/docs/basic-features/data-fetching.md) like [`getStaticProps`](/docs/basic-features/data-fetching.md#getstaticprops-static-generation) or [`getServerSideProps`](/docs/basic-features/data-fetching.md#getserversideprops-server-side-rendering). ## Customizing `renderPage`