diff --git a/docs/basic-features/environment-variables.md b/docs/basic-features/environment-variables.md index 8d378f91d7ac6..a68cb4e7d0e8b 100644 --- a/docs/basic-features/environment-variables.md +++ b/docs/basic-features/environment-variables.md @@ -46,6 +46,11 @@ export async function getStaticProps() { } ``` +> **Note**: In order to keep server-only secrets safe, Next.js replaces `process.env.*` with the correct values +> at build time. This means that `process.env` is not a standard JavaScript object, so you’re not able to +> use [object destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment). +> Environment variables must be referenced as e.g. `process.env.NEXT_PUBLIC_PUBLISHABLE_KEY`, _not_ `const { NEXT_PUBLIC_PUBLISHABLE_KEY } = process.env`. + > **Note**: Next.js will automatically expand variables (`$VAR`) inside of your `.env*` files. > This allows you to reference other secrets, like so: > diff --git a/errors/can-not-output-to-static.md b/errors/can-not-output-to-static.md new file mode 100644 index 0000000000000..b949bc06ffb7a --- /dev/null +++ b/errors/can-not-output-to-static.md @@ -0,0 +1,15 @@ +# Cannot output to /static + +#### Why This Error Occurred + +Either you set `distDir` to `static` in your `next.config.js` or during `next export` you tried to export to the `static` directory. + +This is not allowed due to `static` being a special folder in Next.js used to serve static assets. + +#### Possible Ways to Fix It + +Use a different `distDir` or export to a different folder. + +### Useful Links + +- [Static file serving docs](https://nextjs.org/docs/basic-features/static-file-serving) diff --git a/examples/blog-starter-typescript/package.json b/examples/blog-starter-typescript/package.json index 561fd67d33286..9b8cd0f86c8a7 100644 --- a/examples/blog-starter-typescript/package.json +++ b/examples/blog-starter-typescript/package.json @@ -24,6 +24,8 @@ "@types/node": "^14.0.1", "@types/react": "^16.9.35", "@types/react-dom": "^16.9.8", + "autoprefixer": "^10.2.1", + "postcss": "^8.2.4", "postcss-preset-env": "^6.7.0", "tailwindcss": "^2.0.2" }, diff --git a/examples/blog-starter/package.json b/examples/blog-starter/package.json index 134d656d9364f..a49f724f21bfd 100644 --- a/examples/blog-starter/package.json +++ b/examples/blog-starter/package.json @@ -17,10 +17,10 @@ "remark-html": "13.0.1" }, "devDependencies": { - "autoprefixer": "10.0.4", - "postcss": "8.1.10", + "autoprefixer": "^10.2.1", + "postcss": "^8.2.4", "postcss-preset-env": "^6.7.0", - "tailwindcss": "2.0.1" + "tailwindcss": "^2.0.2" }, "license": "MIT" } diff --git a/examples/cms-graphcms/components/avatar.js b/examples/cms-graphcms/components/avatar.js index 2dcc7eee10693..6777f50313593 100644 --- a/examples/cms-graphcms/components/avatar.js +++ b/examples/cms-graphcms/components/avatar.js @@ -1,7 +1,16 @@ +import Image from 'next/image' + export default function Avatar({ name, picture }) { return (
- {name} +
+ {name} +
{name}
) diff --git a/examples/cms-graphcms/components/cover-image.js b/examples/cms-graphcms/components/cover-image.js index 560c40d4c711b..a4cda9cc8ba75 100644 --- a/examples/cms-graphcms/components/cover-image.js +++ b/examples/cms-graphcms/components/cover-image.js @@ -1,9 +1,10 @@ -import cn from 'classnames' +import Image from 'next/image' import Link from 'next/link' +import cn from 'classnames' export default function CoverImage({ title, url, slug }) { const image = ( - {`Cover More Stories -
+
{posts.map((post) => ( { - const server = express() - - server.get('/service-worker.js', (req, res) => { - app.serveStatic(req, res, './.next/service-worker.js') - }) - - const serviceWorkers = [ - { - filename: 'service-worker.js', - path: './.next/service-worker.js', - }, - { - filename: 'firebase-messaging-sw.js', - path: './static/firebase-messaging-sw.js', - }, - ] - - serviceWorkers.forEach(({ filename, path }) => { - server.get(`/${filename}`, (req, res) => { - app.serveStatic(req, res, path) - }) - }) - - server.get('*', (req, res) => { - return handle(req, res) - }) - - server.listen(port, (err) => { - if (err) throw err - console.log(`> Ready on http://localhost:${port}`) - }) -}) diff --git a/examples/with-graphql-hooks/components/app.js b/examples/with-graphql-hooks/components/app.js index 97c5647a6f01a..5a0ce7dee5c9b 100644 --- a/examples/with-graphql-hooks/components/app.js +++ b/examples/with-graphql-hooks/components/app.js @@ -1,44 +1,3 @@ export default function App({ children }) { - return ( -
- {children} - -
- ) + return
{children}
} diff --git a/examples/with-graphql-hooks/components/post-list.js b/examples/with-graphql-hooks/components/post-list.js index 45707ece6fec2..3cf8a132433b1 100644 --- a/examples/with-graphql-hooks/components/post-list.js +++ b/examples/with-graphql-hooks/components/post-list.js @@ -4,9 +4,9 @@ import ErrorMessage from './error-message' import PostUpvoter from './post-upvoter' import Submit from './submit' -export const allPostsQuery = ` +export const ALL_POSTS_QUERY = ` query allPosts($first: Int!, $skip: Int!) { - allPosts(orderBy: createdAt_DESC, first: $first, skip: $skip) { + allPosts(orderBy: { createdAt: desc }, first: $first, skip: $skip) { id title votes @@ -32,7 +32,7 @@ export const allPostsQueryOptions = (skip = 0) => ({ export default function PostList() { const [skip, setSkip] = useState(0) const { loading, error, data, refetch } = useQuery( - allPostsQuery, + ALL_POSTS_QUERY, allPostsQueryOptions(skip) ) @@ -40,8 +40,8 @@ export default function PostList() { if (!data) return
Loading
const { allPosts, _allPostsMeta } = data - const areMorePosts = allPosts.length < _allPostsMeta.count + return ( <> {areMorePosts ? ( - ) : ( '' )} - ) diff --git a/examples/with-graphql-hooks/components/post-upvoter.js b/examples/with-graphql-hooks/components/post-upvoter.js index 98ea3ddf9656f..d2266c40a9fef 100644 --- a/examples/with-graphql-hooks/components/post-upvoter.js +++ b/examples/with-graphql-hooks/components/post-upvoter.js @@ -2,11 +2,11 @@ import React from 'react' import { useMutation } from 'graphql-hooks' const UPDATE_POST = ` - mutation updatePost($id: ID!, $votes: Int) { - updatePost(id: $id, votes: $votes) { + mutation votePost($id: String!) { + votePost(id: $id) { id - __typename votes + __typename } } ` @@ -16,12 +16,12 @@ export default function PostUpvoter({ votes, id, onUpdate }) { return ( ) } diff --git a/examples/with-graphql-hooks/lib/graphql-client.js b/examples/with-graphql-hooks/lib/graphql-client.js index e7d8ad8258495..50750d6afaada 100644 --- a/examples/with-graphql-hooks/lib/graphql-client.js +++ b/examples/with-graphql-hooks/lib/graphql-client.js @@ -7,7 +7,7 @@ let graphQLClient function createClient(initialState) { return new GraphQLClient({ ssrMode: typeof window === 'undefined', - url: 'https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn', // Server URL (must be absolute) + url: 'https://nextjs-graphql-with-prisma-simple.vercel.app/api', // Server URL (must be absolute) cache: memCache({ initialState }), }) } diff --git a/examples/with-graphql-hooks/package.json b/examples/with-graphql-hooks/package.json index 2bc97a22cd0dc..8960f769307c4 100644 --- a/examples/with-graphql-hooks/package.json +++ b/examples/with-graphql-hooks/package.json @@ -8,11 +8,11 @@ }, "license": "MIT", "dependencies": { - "graphql-hooks": "^4.5.0", - "graphql-hooks-memcache": "^1.3.3", + "graphql-hooks": "^5.1.0", + "graphql-hooks-memcache": "^2.1.0", "next": "latest", "prop-types": "^15.7.2", - "react": "^16.8.2", - "react-dom": "^16.8.2" + "react": "^17.0.1", + "react-dom": "^17.0.1" } } diff --git a/examples/with-graphql-hooks/pages/_app.js b/examples/with-graphql-hooks/pages/_app.js index 9420b692f11ee..c72524f1a03ac 100644 --- a/examples/with-graphql-hooks/pages/_app.js +++ b/examples/with-graphql-hooks/pages/_app.js @@ -1,3 +1,4 @@ +import '../styles.css' import { ClientContext } from 'graphql-hooks' import { useGraphQLClient } from '../lib/graphql-client' diff --git a/examples/with-graphql-hooks/pages/index.js b/examples/with-graphql-hooks/pages/index.js index 85aa71d251cb4..dc9ec59025d1b 100644 --- a/examples/with-graphql-hooks/pages/index.js +++ b/examples/with-graphql-hooks/pages/index.js @@ -3,7 +3,7 @@ import graphQLRequest from '../lib/graphql-request' import App from '../components/app' import Header from '../components/header' import PostList, { - allPostsQuery, + ALL_POSTS_QUERY, allPostsQueryOptions, } from '../components/post-list' @@ -19,7 +19,7 @@ export default function Home() { export async function getStaticProps() { const client = initializeGraphQL() - await graphQLRequest(client, allPostsQuery, allPostsQueryOptions()) + await graphQLRequest(client, ALL_POSTS_QUERY, allPostsQueryOptions()) return { props: { diff --git a/examples/with-graphql-hooks/styles.css b/examples/with-graphql-hooks/styles.css new file mode 100644 index 0000000000000..dd28550255ba9 --- /dev/null +++ b/examples/with-graphql-hooks/styles.css @@ -0,0 +1,104 @@ +* { + font-family: Menlo, Monaco, 'Lucida Console', 'Liberation Mono', + 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, + serif; +} +body { + margin: 0; + padding: 25px 50px; +} +a { + color: #22bad9; +} +p { + font-size: 14px; + line-height: 24px; +} +article { + margin: 0 auto; + max-width: 650px; +} +form { + border-bottom: 1px solid #ececec; + padding-bottom: 20px; + margin-bottom: 20px; +} +h1 { + font-size: 20px; +} +input { + display: block; + margin-bottom: 10px; +} +section { + padding-bottom: 20px; +} +li { + display: block; + margin-bottom: 10px; +} +div { + align-items: center; + display: flex; +} +a { + font-size: 14px; + margin-right: 10px; + text-decoration: none; + padding-bottom: 0; + border: 0; +} +span { + font-size: 14px; + margin-right: 5px; +} +ul { + margin: 0; + padding: 0; +} + +button:before { + align-self: center; + border-style: solid; + content: ''; + height: 0; + margin-right: 5px; + width: 0; +} + +button { + align-items: center; + background-color: #22bad9; + border: 0; + color: white; + display: flex; + padding: 5px 7px; +} +button:active { + background-color: #1b9db7; + transition: background-color 0.3s; +} + +button:focus { + outline: none; +} + +button:active { + background-color: transparent; +} + +.upvote { + background-color: transparent; + border: 1px solid #e4e4e4; + color: #000; +} + +.upvote:before { + border-width: 0 4px 6px 4px; + border-color: transparent transparent #000000 transparent; +} + +.more:before { + border-width: 6px 4px 0 4px; + border-color: #ffffff transparent transparent transparent; +} diff --git a/examples/with-supabase-auth-realtime-db/README.md b/examples/with-supabase-auth-realtime-db/README.md index a84917ffb2ea9..537029ce5f8d5 100644 --- a/examples/with-supabase-auth-realtime-db/README.md +++ b/examples/with-supabase-auth-realtime-db/README.md @@ -38,7 +38,7 @@ Sign up to Supabase - [https://app.supabase.io](https://app.supabase.io) and cre Once your database has started, run the "Slack Clone" quickstart. -![Slack Clone Quick Start](https://user-images.githubusercontent.com/10214025/88916135-1b1d7a00-d298-11ea-82e7-e2c18314e805.png) +![Slack Clone Quick Start](./docs/quickstart.png) ### Step 3. Set up environment variables diff --git a/examples/with-supabase-auth-realtime-db/docs/quickstart.png b/examples/with-supabase-auth-realtime-db/docs/quickstart.png new file mode 100644 index 0000000000000..e406fc9c0826f Binary files /dev/null and b/examples/with-supabase-auth-realtime-db/docs/quickstart.png differ diff --git a/examples/with-supabase-auth-realtime-db/package.json b/examples/with-supabase-auth-realtime-db/package.json index 38ba2ea0b6623..cd117d52fadca 100644 --- a/examples/with-supabase-auth-realtime-db/package.json +++ b/examples/with-supabase-auth-realtime-db/package.json @@ -12,7 +12,11 @@ "next": "latest", "react": "^16.13.1", "react-dom": "^16.13.1", - "sass": "^1.26.2", - "tailwindcss": "^1.1.4" + "sass": "^1.26.2" + }, + "devDependencies": { + "autoprefixer": "10.1.0", + "postcss": "8.2.2", + "tailwindcss": "2.0.2" } } diff --git a/examples/with-supabase-auth-realtime-db/postcss.config.js b/examples/with-supabase-auth-realtime-db/postcss.config.js new file mode 100644 index 0000000000000..33ad091d26d8a --- /dev/null +++ b/examples/with-supabase-auth-realtime-db/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/examples/with-supabase-auth-realtime-db/tailwind.config.js b/examples/with-supabase-auth-realtime-db/tailwind.config.js new file mode 100644 index 0000000000000..c00fe06cdbeb2 --- /dev/null +++ b/examples/with-supabase-auth-realtime-db/tailwind.config.js @@ -0,0 +1,11 @@ +module.exports = { + purge: ['./pages/**/*.js', './components/**/*.js'], + darkMode: false, // or 'media' or 'class' + theme: { + extend: {}, + }, + variants: { + extend: {}, + }, + plugins: [], +} diff --git a/examples/with-tailwindcss/README.md b/examples/with-tailwindcss/README.md index e185165506a38..06c729ea5bbee 100644 --- a/examples/with-tailwindcss/README.md +++ b/examples/with-tailwindcss/README.md @@ -1,6 +1,6 @@ # Tailwind CSS example -This is an example of using [Tailwind CSS](https://tailwindcss.com) in a Next.js project. +This example is a basic starting point for using [Tailwind CSS](https://tailwindcss.com) with Next.js. ## Deploy your own @@ -22,8 +22,9 @@ Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&ut ## Notes -This example is a basic starting point for using [Tailwind CSS](https://tailwindcss.com) with Next.js. It includes the following [PostCSS](https://github.com/postcss/postcss) plugins: +This example includes the following [PostCSS](https://github.com/postcss/postcss) plugins: -- [postcss-preset-env](https://preset-env.cssdb.org/) - Adds stage 2+ features and autoprefixes +- [tailwindcss](https://tailwindcss.com) - utility-first CSS framework +- [autoprefixer](https://github.com/postcss/autoprefixer) - plugin to parse CSS and add vendor prefixes to CSS rules using values from [Can I Use](https://caniuse.com). To control the generated stylesheet's filesize, this example uses Tailwind CSS' [`purge` option](https://tailwindcss.com/docs/controlling-file-size/#removing-unused-css) to remove unused CSS. diff --git a/examples/with-three-js/components/Bird.js b/examples/with-three-js/components/Bird.js index e2e71022ece83..024dcd5f06b9d 100644 --- a/examples/with-three-js/components/Bird.js +++ b/examples/with-three-js/components/Bird.js @@ -25,14 +25,14 @@ const Bird = ({ speed, factor, url, ...props }) => { - + diff --git a/examples/with-three-js/next.config.js b/examples/with-three-js/next.config.js index e87bd46b091ae..588b99c9e65bd 100644 --- a/examples/with-three-js/next.config.js +++ b/examples/with-three-js/next.config.js @@ -1,7 +1,3 @@ -const withTM = require('next-transpile-modules')([ - 'drei', - 'three', - 'postprocessing', -]) +const withTM = require('next-transpile-modules')(['drei', 'three']) module.exports = withTM() diff --git a/examples/with-three-js/package.json b/examples/with-three-js/package.json index 5d4dac6aba916..8ed25de54441e 100644 --- a/examples/with-three-js/package.json +++ b/examples/with-three-js/package.json @@ -8,15 +8,15 @@ "start": "next start" }, "dependencies": { - "drei": "0.0.60", - "next": "9.4.4", - "react": "16.13.1", - "react-dom": "16.13.1", - "react-three-fiber": "4.2.12", - "three": "0.118.3" + "drei": "2.2.13", + "next": "10.0.5", + "react": "17.0.1", + "react-dom": "17.0.1", + "react-three-fiber": "5.3.11", + "three": "0.124.0" }, "devDependencies": { - "next-transpile-modules": "4.0.2" + "next-transpile-modules": "6.0.0" }, "license": "MIT" } diff --git a/examples/with-three-js/pages/birds.js b/examples/with-three-js/pages/birds.js index 1e95d62b3e5bd..0f7f2717c7c13 100644 --- a/examples/with-three-js/pages/birds.js +++ b/examples/with-three-js/pages/birds.js @@ -1,7 +1,7 @@ import dynamic from 'next/dynamic' import { Suspense } from 'react' import { Canvas } from 'react-three-fiber' -import { OrbitControls, StandardEffects } from 'drei' +import { OrbitControls } from 'drei' const Bird = dynamic(() => import('../components/Bird'), { ssr: false }) @@ -41,7 +41,6 @@ const BirdsPage = (props) => { - diff --git a/examples/with-three-js/pages/boxes.js b/examples/with-three-js/pages/boxes.js index 03b8ae138b479..f2cc839f4993e 100644 --- a/examples/with-three-js/pages/boxes.js +++ b/examples/with-three-js/pages/boxes.js @@ -1,6 +1,6 @@ -import { useRef, useState, Suspense } from 'react' +import { useRef, useState } from 'react' import { Canvas, useFrame } from 'react-three-fiber' -import { OrbitControls, StandardEffects, Box } from 'drei' +import { OrbitControls, Box } from 'drei' const MyBox = (props) => { const mesh = useRef() @@ -39,9 +39,6 @@ const BoxesPage = () => { - - - , ] } diff --git a/license.md b/license.md index fa5d39b6213f8..b708f872cb51e 100644 --- a/license.md +++ b/license.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2020 Vercel, Inc. +Copyright (c) 2021 Vercel, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/package.json b/package.json index 2be79259ff215..a2f6710414e1b 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "npm-run-all": "4.1.5", "nprogress": "0.2.0", "pixrem": "5.0.0", - "pnpm": "5.8.0", + "pnpm": "5.14.3", "postcss-nested": "4.2.1", "postcss-pseudoelements": "5.0.0", "postcss-short-size": "4.0.0", diff --git a/packages/next-codemod/license.md b/packages/next-codemod/license.md index fa5d39b6213f8..b708f872cb51e 100644 --- a/packages/next-codemod/license.md +++ b/packages/next-codemod/license.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2020 Vercel, Inc. +Copyright (c) 2021 Vercel, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/next-mdx/license.md b/packages/next-mdx/license.md index fa5d39b6213f8..b708f872cb51e 100644 --- a/packages/next-mdx/license.md +++ b/packages/next-mdx/license.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2020 Vercel, Inc. +Copyright (c) 2021 Vercel, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/next/build/babel/preset.ts b/packages/next/build/babel/preset.ts index be7415e6b1c10..5215020169879 100644 --- a/packages/next/build/babel/preset.ts +++ b/packages/next/build/babel/preset.ts @@ -77,6 +77,10 @@ module.exports = ( // Default to production mode if not `test` nor `development`: const isProduction = !(isTest || isDevelopment) + const isBabelLoader = api.caller( + (caller: any) => !!caller && caller.name === 'babel-loader' + ) + const useJsxRuntime = options['preset-react']?.runtime === 'automatic' || (Boolean(api.caller((caller: any) => !!caller && caller.hasJsxRuntime)) && @@ -180,7 +184,7 @@ module.exports = ( helpers: true, regenerator: true, useESModules: supportsESM && presetEnvConfig.modules !== 'commonjs', - absoluteRuntime: process.versions.pnp + absoluteRuntime: isBabelLoader ? dirname(require.resolve('@babel/runtime/package.json')) : undefined, ...options['transform-runtime'], diff --git a/packages/next/build/plugins/collect-plugins.ts b/packages/next/build/plugins/collect-plugins.ts index c23e876359c0e..bb5c5e33c96a7 100644 --- a/packages/next/build/plugins/collect-plugins.ts +++ b/packages/next/build/plugins/collect-plugins.ts @@ -1,7 +1,6 @@ import findUp from 'next/dist/compiled/find-up' import { promises } from 'fs' import path from 'path' -import resolve from 'next/dist/compiled/resolve/index.js' import { execOnce } from '../../next-server/lib/utils' const { version } = require('next/package.json') @@ -213,10 +212,7 @@ async function _collectPlugins( nextPluginNames.map((name) => collectPluginMeta( env, - resolve.sync(path.join(name, 'package.json'), { - basedir: dir, - preserveSymlinks: true, - }), + require.resolve(path.join(name, 'package.json'), { paths: [dir] }), name, version ) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index a40321b4f75f4..1b2e33c7c6e53 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -18,7 +18,6 @@ import { import { fileExists } from '../lib/file-exists' import { getPackageVersion } from '../lib/get-package-version' import { Rewrite } from '../lib/load-custom-routes' -import { resolveRequest } from '../lib/resolve-request' import { getTypeScriptConfiguration } from '../lib/typescript/getTypeScriptConfiguration' import { CLIENT_STATIC_FILES_RUNTIME_MAIN, @@ -306,7 +305,7 @@ export default async function getBaseWebpackConfig( let typeScriptPath: string | undefined try { - typeScriptPath = resolveRequest('typescript', `${dir}/`) + typeScriptPath = require.resolve('typescript', { paths: [dir] }) } catch (_) {} const tsConfigPath = path.join(dir, 'tsconfig.json') const useTypeScript = Boolean( @@ -607,7 +606,7 @@ export default async function getBaseWebpackConfig( // exist. let res: string try { - res = resolveRequest(request, `${context}/`) + res = require.resolve(request, { paths: [context] }) } catch (err) { // If the request cannot be resolved, we need to tell webpack to // "bundle" it so that webpack shows an error (that it cannot be @@ -645,7 +644,7 @@ export default async function getBaseWebpackConfig( // we need to bundle the code (even if it _should_ be external). let baseRes: string | null try { - baseRes = resolveRequest(request, `${dir}/`) + baseRes = require.resolve(request, { paths: [dir] }) } catch (err) { baseRes = null } @@ -911,14 +910,13 @@ export default async function getBaseWebpackConfig( }, plugins: [ hasReactRefresh && new ReactRefreshWebpackPlugin(), - // Makes sure `Buffer` is polyfilled in client-side bundles (same behavior as webpack 4) + // Makes sure `Buffer` and `process` are polyfilled in client-side bundles (same behavior as webpack 4) isWebpack5 && !isServer && - new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'] }), - // Makes sure `process` is polyfilled in client-side bundles (same behavior as webpack 4) - isWebpack5 && - !isServer && - new webpack.ProvidePlugin({ process: ['process'] }), + new webpack.ProvidePlugin({ + Buffer: [require.resolve('buffer'), 'Buffer'], + process: [require.resolve('process')], + }), // This plugin makes sure `output.filename` is used for entry chunks !isWebpack5 && new ChunkNamesPlugin(), new webpack.DefinePlugin({ @@ -1422,29 +1420,32 @@ export default async function getBaseWebpackConfig( try { // Resolve the version of `@zeit/next-css` as depended on by the Sass, // Less or Stylus plugin. - const correctNextCss = resolveRequest( - '@zeit/next-css', - isCss - ? // Resolve `@zeit/next-css` from the base directory - `${dir}/` - : // Else, resolve it from the specific plugins - require.resolve( - isSass - ? '@zeit/next-sass' - : isLess - ? '@zeit/next-less' - : isStylus - ? '@zeit/next-stylus' - : 'next' - ) - ) + const correctNextCss = require.resolve('@zeit/next-css', { + paths: [ + isCss + ? // Resolve `@zeit/next-css` from the base directory + dir + : // Else, resolve it from the specific plugins + require.resolve( + isSass + ? '@zeit/next-sass' + : isLess + ? '@zeit/next-less' + : isStylus + ? '@zeit/next-stylus' + : 'next' + ), + ], + }) // If we found `@zeit/next-css` ... if (correctNextCss) { // ... resolve the version of `css-loader` shipped with that // package instead of whichever was hoisted highest in your // `node_modules` tree. - const correctCssLoader = resolveRequest(use.loader, correctNextCss) + const correctCssLoader = require.resolve(use.loader, { + paths: [correctNextCss], + }) if (correctCssLoader) { // We saved the user from a failed build! use.loader = correctCssLoader diff --git a/packages/next/build/webpack/config/blocks/css/plugins.ts b/packages/next/build/webpack/config/blocks/css/plugins.ts index c1fd7aba2dc78..7aa6d22e41d95 100644 --- a/packages/next/build/webpack/config/blocks/css/plugins.ts +++ b/packages/next/build/webpack/config/blocks/css/plugins.ts @@ -1,6 +1,5 @@ import chalk from 'chalk' import { findConfig } from '../../../../../lib/find-config' -import { resolveRequest } from '../../../../../lib/resolve-request' import browserslist from 'browserslist' type CssPluginCollection_Array = (string | [string, boolean | object])[] @@ -57,7 +56,7 @@ async function loadPlugin( throw new Error(genericErrorText) } - const pluginPath = resolveRequest(pluginName, `${dir}/`) + const pluginPath = require.resolve(pluginName, { paths: [dir] }) if (isIgnoredPlugin(pluginPath)) { return false } else if (options === true) { diff --git a/packages/next/compiled/resolve/LICENSE b/packages/next/compiled/resolve/LICENSE deleted file mode 100644 index ee27ba4b4412b..0000000000000 --- a/packages/next/compiled/resolve/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -This software is released under the MIT license: - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/next/compiled/resolve/index.js b/packages/next/compiled/resolve/index.js deleted file mode 100644 index e0e41629c41a2..0000000000000 --- a/packages/next/compiled/resolve/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports=(()=>{var e={731:e=>{"use strict";var r=process.platform==="win32";var n=/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;var t=/^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/;var i={};function win32SplitPath(e){var r=n.exec(e),i=(r[1]||"")+(r[2]||""),a=r[3]||"";var o=t.exec(a),s=o[1],l=o[2],u=o[3];return[i,s,l,u]}i.parse=function(e){if(typeof e!=="string"){throw new TypeError("Parameter 'pathString' must be a string, not "+typeof e)}var r=win32SplitPath(e);if(!r||r.length!==4){throw new TypeError("Invalid path '"+e+"'")}return{root:r[0],dir:r[0]+r[1].slice(0,-1),base:r[2],ext:r[3],name:r[2].slice(0,r[2].length-r[3].length)}};var a=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;var o={};function posixSplitPath(e){return a.exec(e).slice(1)}o.parse=function(e){if(typeof e!=="string"){throw new TypeError("Parameter 'pathString' must be a string, not "+typeof e)}var r=posixSplitPath(e);if(!r||r.length!==4){throw new TypeError("Invalid path '"+e+"'")}r[1]=r[1]||"";r[2]=r[2]||"";r[3]=r[3]||"";return{root:r[0],dir:r[0]+r[1].slice(0,-1),base:r[2],ext:r[3],name:r[2].slice(0,r[2].length-r[3].length)}};if(r)e.exports=i.parse;else e.exports=o.parse;e.exports.posix=o.parse;e.exports.win32=i.parse},283:(e,r,n)=>{var t=n(226);var i=n(125);i.core=t;i.isCore=function isCore(e){return t[e]};i.sync=n(284);r=i;e.exports=i},125:(e,r,n)=>{var t=n(226);var i=n(747);var a=n(622);var o=n(155);var s=n(433);var l=n(990);var u=function isFile(e,r){i.stat(e,function(e,n){if(!e){return r(null,n.isFile()||n.isFIFO())}if(e.code==="ENOENT"||e.code==="ENOTDIR")return r(null,false);return r(e)})};var f=function isDirectory(e,r){i.stat(e,function(e,n){if(!e){return r(null,n.isDirectory())}if(e.code==="ENOENT"||e.code==="ENOTDIR")return r(null,false);return r(e)})};e.exports=function resolve(e,r,n){var c=n;var p=r;if(typeof r==="function"){c=p;p={}}if(typeof e!=="string"){var v=new TypeError("Path must be a string.");return process.nextTick(function(){c(v)})}p=l(e,p);var d=p.isFile||u;var y=p.isDirectory||f;var _=p.readFile||i.readFile;var g=p.extensions||[".js"];var m=p.basedir||a.dirname(o());var h=p.filename||m;p.paths=p.paths||[];var F=a.resolve(m);if(p.preserveSymlinks===false){i.realpath(F,function(e,r){if(e&&e.code!=="ENOENT")c(v);else init(e?F:r)})}else{init(F)}var w;function init(r){if(/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/.test(e)){w=a.resolve(r,e);if(e===".."||e.slice(-1)==="/")w+="/";if(/\/$/.test(e)&&w===r){loadAsDirectory(w,p.package,onfile)}else loadAsFile(w,p.package,onfile)}else loadNodeModules(e,r,function(r,n,i){if(r)c(r);else if(n)c(null,n,i);else if(t[e])return c(null,e);else{var a=new Error("Cannot find module '"+e+"' from '"+h+"'");a.code="MODULE_NOT_FOUND";c(a)}})}function onfile(r,n,t){if(r)c(r);else if(n)c(null,n,t);else loadAsDirectory(w,function(r,n,t){if(r)c(r);else if(n)c(null,n,t);else{var i=new Error("Cannot find module '"+e+"' from '"+h+"'");i.code="MODULE_NOT_FOUND";c(i)}})}function loadAsFile(e,r,n){var t=r;var i=n;if(typeof t==="function"){i=t;t=undefined}var o=[""].concat(g);load(o,e,t);function load(e,r,n){if(e.length===0)return i(null,undefined,n);var t=r+e[0];var o=n;if(o)onpkg(null,o);else loadpkg(a.dirname(t),onpkg);function onpkg(n,s,l){o=s;if(n)return i(n);if(l&&o&&p.pathFilter){var u=a.relative(l,t);var f=u.slice(0,u.length-e[0].length);var c=p.pathFilter(o,r,f);if(c)return load([""].concat(g.slice()),a.resolve(l,c),o)}d(t,onex)}function onex(n,a){if(n)return i(n);if(a)return i(null,t,o);load(e.slice(1),r,o)}}}function loadpkg(e,r){if(e===""||e==="/")return r(null);if(process.platform==="win32"&&/^\w:[/\\]*$/.test(e)){return r(null)}if(/[/\\]node_modules[/\\]*$/.test(e))return r(null);var n=a.join(e,"package.json");d(n,function(t,i){if(!i)return loadpkg(a.dirname(e),r);_(n,function(t,i){if(t)r(t);try{var a=JSON.parse(i)}catch(e){}if(a&&p.packageFilter){a=p.packageFilter(a,n)}r(null,a,e)})})}function loadAsDirectory(e,r,n){var t=n;var i=r;if(typeof i==="function"){t=i;i=p.package}var o=a.join(e,"package.json");d(o,function(r,n){if(r)return t(r);if(!n)return loadAsFile(a.join(e,"index"),i,t);_(o,function(r,n){if(r)return t(r);try{var i=JSON.parse(n)}catch(e){}if(p.packageFilter){i=p.packageFilter(i,o)}if(i.main){if(typeof i.main!=="string"){var s=new TypeError("package “"+i.name+"” `main` must be a string");s.code="INVALID_PACKAGE_MAIN";return t(s)}if(i.main==="."||i.main==="./"){i.main="index"}loadAsFile(a.resolve(e,i.main),i,function(r,n,i){if(r)return t(r);if(n)return t(null,n,i);if(!i)return loadAsFile(a.join(e,"index"),i,t);var o=a.resolve(e,i.main);loadAsDirectory(o,i,function(r,n,i){if(r)return t(r);if(n)return t(null,n,i);loadAsFile(a.join(e,"index"),i,t)})});return}loadAsFile(a.join(e,"/index"),i,t)})})}function processDirs(r,n){if(n.length===0)return r(null,undefined);var t=n[0];y(t,isdir);function isdir(i,o){if(i)return r(i);if(!o)return processDirs(r,n.slice(1));var s=a.join(t,e);loadAsFile(s,p.package,onfile)}function onfile(n,i,o){if(n)return r(n);if(i)return r(null,i,o);loadAsDirectory(a.join(t,e),p.package,ondir)}function ondir(e,t,i){if(e)return r(e);if(t)return r(null,t,i);processDirs(r,n.slice(1))}}function loadNodeModules(e,r,n){processDirs(n,s(r,p,e))}}},155:e=>{e.exports=function(){var e=Error.prepareStackTrace;Error.prepareStackTrace=function(e,r){return r};var r=(new Error).stack;Error.prepareStackTrace=e;return r[2].getFileName()}},226:(e,r,n)=>{var t=process.versions&&process.versions.node&&process.versions.node.split(".")||[];function specifierIncluded(e){var r=e.split(" ");var n=r.length>1?r[0]:"=";var i=(r.length>1?r[1]:r[0]).split(".");for(var a=0;a<3;++a){var o=Number(t[a]||0);var s=Number(i[a]||0);if(o===s){continue}if(n==="<"){return o="){return o>=s}else{return false}}return n===">="}function matchesRange(e){var r=e.split(/ ?&& ?/);if(r.length===0){return false}for(var n=0;n{var t=n(622);var i=t.parse||n(731);var a=function getNodeModulesDirs(e,r){var n="/";if(/^([A-Za-z]:)/.test(e)){n=""}else if(/^\\\\/.test(e)){n="\\\\"}var a=[e];var o=i(e);while(o.dir!==a[a.length-1]){a.push(o.dir);o=i(o.dir)}return a.reduce(function(e,i){return e.concat(r.map(function(e){return t.join(n,i,e)}))},[])};e.exports=function nodeModulesPaths(e,r,n){var t=r&&r.moduleDirectory?[].concat(r.moduleDirectory):["node_modules"];if(r&&typeof r.paths==="function"){return r.paths(n,e,function(){return a(e,t)},r)}var i=a(e,t);return r&&r.paths?i.concat(r.paths):i}},990:e=>{e.exports=function(e,r){return r||{}}},284:(e,r,n)=>{var t=n(226);var i=n(747);var a=n(622);var o=n(155);var s=n(433);var l=n(990);var u=function isFile(e){try{var r=i.statSync(e)}catch(e){if(e&&(e.code==="ENOENT"||e.code==="ENOTDIR"))return false;throw e}return r.isFile()||r.isFIFO()};var f=function isDirectory(e){try{var r=i.statSync(e)}catch(e){if(e&&(e.code==="ENOENT"||e.code==="ENOTDIR"))return false;throw e}return r.isDirectory()};e.exports=function(e,r){if(typeof e!=="string"){throw new TypeError("Path must be a string.")}var n=l(e,r);var c=n.isFile||u;var p=n.readFileSync||i.readFileSync;var v=n.isDirectory||f;var d=n.extensions||[".js"];var y=n.basedir||a.dirname(o());var _=n.filename||y;n.paths=n.paths||[];var g=a.resolve(y);if(n.preserveSymlinks===false){try{g=i.realpathSync(g)}catch(e){if(e.code!=="ENOENT"){throw e}}}if(/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/.test(e)){var m=a.resolve(g,e);if(e===".."||e.slice(-1)==="/")m+="/";var h=loadAsFileSync(m)||loadAsDirectorySync(m);if(h)return h}else{var F=loadNodeModulesSync(e,g);if(F)return F}if(t[e])return e;var w=new Error("Cannot find module '"+e+"' from '"+_+"'");w.code="MODULE_NOT_FOUND";throw w;function loadAsFileSync(e){var r=loadpkg(a.dirname(e));if(r&&r.dir&&r.pkg&&n.pathFilter){var t=a.relative(r.dir,e);var i=n.pathFilter(r.pkg,e,t);if(i){e=a.resolve(r.dir,i)}}if(c(e)){return e}for(var o=0;o{"use strict";e.exports=JSON.parse('{"assert":true,"async_hooks":">= 8","buffer_ieee754":"< 0.9.7","buffer":true,"child_process":true,"cluster":true,"console":true,"constants":true,"crypto":true,"_debugger":"< 8","dgram":true,"dns":true,"domain":true,"events":true,"freelist":"< 6","fs":true,"fs/promises":">= 10 && < 10.1","_http_agent":">= 0.11.1","_http_client":">= 0.11.1","_http_common":">= 0.11.1","_http_incoming":">= 0.11.1","_http_outgoing":">= 0.11.1","_http_server":">= 0.11.1","http":true,"http2":">= 8.8","https":true,"inspector":">= 8.0.0","_linklist":"< 8","module":true,"net":true,"node-inspect/lib/_inspect":">= 7.6.0 && < 12","node-inspect/lib/internal/inspect_client":">= 7.6.0 && < 12","node-inspect/lib/internal/inspect_repl":">= 7.6.0 && < 12","os":true,"path":true,"perf_hooks":">= 8.5","process":">= 1","punycode":true,"querystring":true,"readline":true,"repl":true,"smalloc":">= 0.11.5 && < 3","_stream_duplex":">= 0.9.4","_stream_transform":">= 0.9.4","_stream_wrap":">= 1.4.1","_stream_passthrough":">= 0.9.4","_stream_readable":">= 0.9.4","_stream_writable":">= 0.9.4","stream":true,"string_decoder":true,"sys":true,"timers":true,"_tls_common":">= 0.11.13","_tls_legacy":">= 0.11.3 && < 10","_tls_wrap":">= 0.11.3","tls":true,"trace_events":">= 10","tty":true,"url":true,"util":true,"v8/tools/arguments":">= 10 && < 12","v8/tools/codemap":[">= 4.4.0 && < 5",">= 5.2.0 && < 12"],"v8/tools/consarray":[">= 4.4.0 && < 5",">= 5.2.0 && < 12"],"v8/tools/csvparser":[">= 4.4.0 && < 5",">= 5.2.0 && < 12"],"v8/tools/logreader":[">= 4.4.0 && < 5",">= 5.2.0 && < 12"],"v8/tools/profile_view":[">= 4.4.0 && < 5",">= 5.2.0 && < 12"],"v8/tools/splaytree":[">= 4.4.0 && < 5",">= 5.2.0 && < 12"],"v8":">= 1","vm":true,"worker_threads":">= 11.7","zlib":true}')},747:e=>{"use strict";e.exports=require("fs")},622:e=>{"use strict";e.exports=require("path")}};var r={};function __webpack_require__(n){if(r[n]){return r[n].exports}var t=r[n]={exports:{}};var i=true;try{e[n](t,t.exports,__webpack_require__);i=false}finally{if(i)delete r[n]}return t.exports}__webpack_require__.ab=__dirname+"/";return __webpack_require__(283)})(); \ No newline at end of file diff --git a/packages/next/compiled/resolve/package.json b/packages/next/compiled/resolve/package.json deleted file mode 100644 index 7b090b9743e5e..0000000000000 --- a/packages/next/compiled/resolve/package.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"resolve","main":"index.js","author":{"name":"James Halliday","email":"mail@substack.net","url":"http://substack.net"},"license":"MIT"} diff --git a/packages/next/export/index.ts b/packages/next/export/index.ts index fc611fccb91a5..c820e25c8904d 100644 --- a/packages/next/export/index.ts +++ b/packages/next/export/index.ts @@ -252,6 +252,12 @@ export default async function exportApp( ) } + if (outDir === join(dir, 'static')) { + throw new Error( + `The 'static' directory is reserved in Next.js and can not be used as the export out directory. https://err.sh/vercel/next.js/can-not-output-to-static` + ) + } + await recursiveDelete(join(outDir)) await promises.mkdir(join(outDir, '_next', buildId), { recursive: true }) diff --git a/packages/next/lib/get-package-version.ts b/packages/next/lib/get-package-version.ts index 9e2fcbebf8969..2b516a59dcf7a 100644 --- a/packages/next/lib/get-package-version.ts +++ b/packages/next/lib/get-package-version.ts @@ -2,7 +2,6 @@ import { promises as fs } from 'fs' import findUp from 'next/dist/compiled/find-up' import JSON5 from 'next/dist/compiled/json5' import * as path from 'path' -import { resolveRequest } from './resolve-request' type PackageJsonDependencies = { dependencies: Record @@ -52,7 +51,9 @@ export async function getPackageVersion({ : `${cwd}/` try { - const targetPath = resolveRequest(`${name}/package.json`, cwd2) + const targetPath = require.resolve(`${name}/package.json`, { + paths: [cwd2], + }) const targetContent = await fs.readFile(targetPath, 'utf-8') return JSON5.parse(targetContent).version ?? null } catch { diff --git a/packages/next/lib/resolve-request.ts b/packages/next/lib/resolve-request.ts deleted file mode 100644 index e15f3d737bde0..0000000000000 --- a/packages/next/lib/resolve-request.ts +++ /dev/null @@ -1,18 +0,0 @@ -import resolve from 'next/dist/compiled/resolve/index.js' -import path from 'path' - -export function resolveRequest(req: string, issuer: string): string { - // The `resolve` package is prebuilt through ncc, which prevents - // PnP from being able to inject itself into it. To circumvent - // this, we simply use PnP directly when available. - if (process.versions.pnp) { - const { resolveRequest: pnpResolveRequest } = require(`pnpapi`) - return pnpResolveRequest(req, issuer, { considerBuiltins: false }) - } else { - const basedir = - issuer.endsWith(path.posix.sep) || issuer.endsWith(path.win32.sep) - ? issuer - : path.dirname(issuer) - return resolve.sync(req, { basedir }) - } -} diff --git a/packages/next/lib/typescript/diagnosticFormatter.ts b/packages/next/lib/typescript/diagnosticFormatter.ts index 7b50c9ada0efc..6d183431415e7 100644 --- a/packages/next/lib/typescript/diagnosticFormatter.ts +++ b/packages/next/lib/typescript/diagnosticFormatter.ts @@ -45,7 +45,7 @@ export async function getFormattedDiagnostic( const character = pos.character + 1 let fileName = path.posix.normalize( - path.relative(baseDir, diagnostic.file.fileName).replace(/\\/, '/') + path.relative(baseDir, diagnostic.file.fileName).replace(/\\/g, '/') ) if (!fileName.startsWith('.')) { fileName = './' + fileName diff --git a/packages/next/lib/typescript/hasNecessaryDependencies.ts b/packages/next/lib/typescript/hasNecessaryDependencies.ts index 6dac0650c0744..5e49969784701 100644 --- a/packages/next/lib/typescript/hasNecessaryDependencies.ts +++ b/packages/next/lib/typescript/hasNecessaryDependencies.ts @@ -2,7 +2,6 @@ import chalk from 'chalk' import path from 'path' import { fileExists } from '../file-exists' import { getOxfordCommaList } from '../oxford-comma-list' -import { resolveRequest } from '../resolve-request' import { FatalTypeScriptError } from './FatalTypeScriptError' const requiredPackages = [ @@ -22,7 +21,7 @@ export async function hasNecessaryDependencies( const missingPackages = requiredPackages.filter((p) => { try { - resolutions.set(p.pkg, resolveRequest(p.file, path.join(baseDir, '/'))) + resolutions.set(p.pkg, require.resolve(p.file, { paths: [baseDir] })) return false } catch (_) { return true diff --git a/packages/next/license.md b/packages/next/license.md index fa5d39b6213f8..b708f872cb51e 100644 --- a/packages/next/license.md +++ b/packages/next/license.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2020 Vercel, Inc. +Copyright (c) 2021 Vercel, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/next/package.json b/packages/next/package.json index 761abd06dbffa..c5d79017f16f9 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -172,7 +172,6 @@ "@types/react": "16.9.17", "@types/react-dom": "16.9.4", "@types/react-is": "16.7.1", - "@types/resolve": "0.0.8", "@types/semver": "7.3.1", "@types/send": "0.14.4", "@types/sharp": "0.26.0", @@ -220,7 +219,6 @@ "postcss-preset-env": "6.7.0", "postcss-scss": "3.0.4", "recast": "0.18.5", - "resolve": "1.11.0", "semver": "7.3.2", "send": "0.17.1", "source-map": "0.6.1", diff --git a/packages/next/taskfile.js b/packages/next/taskfile.js index 0712a9be2211d..89b8d525ffb75 100644 --- a/packages/next/taskfile.js +++ b/packages/next/taskfile.js @@ -404,16 +404,6 @@ export async function ncc_recast(task, opts) { .target('compiled/recast') } // eslint-disable-next-line camelcase -// NB: Used by other dependencies, but Vercel version is a duplicate -// version so can be inlined anyway (although may change in future) -externals['resolve'] = 'next/dist/compiled/resolve' -export async function ncc_resolve(task, opts) { - await task - .source(opts.src || relative(__dirname, require.resolve('resolve'))) - .ncc({ packageName: 'resolve', externals }) - .target('compiled/resolve') -} -// eslint-disable-next-line camelcase externals['schema-utils'] = 'next/dist/compiled/schema-utils' export async function ncc_schema_utils(task, opts) { await task @@ -576,7 +566,6 @@ export async function ncc(task) { 'ncc_postcss_preset_env', 'ncc_postcss_scss', 'ncc_recast', - 'ncc_resolve', 'ncc_schema_utils', 'ncc_send', 'ncc_source_map', diff --git a/packages/next/types/misc.d.ts b/packages/next/types/misc.d.ts index aa1832b69dadf..afb31154d8125 100644 --- a/packages/next/types/misc.d.ts +++ b/packages/next/types/misc.d.ts @@ -145,10 +145,6 @@ declare module 'next/dist/compiled/recast' { import m from 'recast' export = m } -declare module 'next/dist/compiled/resolve/index.js' { - import m from 'resolve' - export = m -} declare module 'next/dist/compiled/send' { import m from 'send' export = m diff --git a/test-pnp.sh b/test-pnp.sh index 6ea70845a22b8..43564baf466a2 100644 --- a/test-pnp.sh +++ b/test-pnp.sh @@ -1,7 +1,10 @@ declare -a testCases=( "with-typescript" "with-next-sass" + # Tests @next/mdx "with-mdx" + # Tests babel config + "with-styled-components" ) set -e @@ -25,6 +28,7 @@ do touch yarn.lock yarn set version berry yarn config set pnpFallbackMode none + yarn config set enableGlobalCache true yarn link --all --private -r ../.. yarn build diff --git a/test/integration/errors-on-output-to-public/test/index.test.js b/test/integration/errors-on-output-to-public/test/index.test.js index b094b29a74fda..be7e9b9bcd1f4 100644 --- a/test/integration/errors-on-output-to-public/test/index.test.js +++ b/test/integration/errors-on-output-to-public/test/index.test.js @@ -13,7 +13,7 @@ describe('Errors on output to public', () => { await fs.writeFile(nextConfig, `module.exports = { distDir: 'public' }`) const results = await nextBuild(appDir, [], { stdout: true, stderr: true }) expect(results.stdout + results.stderr).toMatch( - /The 'public' directory is reserved in Next.js and can not be set as/ + /The 'public' directory is reserved in Next\.js and can not be set as/ ) await fs.remove(nextConfig) }) @@ -31,7 +31,7 @@ describe('Errors on output to public', () => { } ) expect(results.stdout + results.stderr).toMatch( - /The 'public' directory is reserved in Next.js and can not be used as/ + /The 'public' directory is reserved in Next\.js and can not be used as/ ) }) }) diff --git a/test/integration/errors-on-output-to-static/pages/index.js b/test/integration/errors-on-output-to-static/pages/index.js new file mode 100644 index 0000000000000..0957a987fc2f2 --- /dev/null +++ b/test/integration/errors-on-output-to-static/pages/index.js @@ -0,0 +1 @@ +export default () => 'hi' diff --git a/test/integration/errors-on-output-to-static/test/index.test.js b/test/integration/errors-on-output-to-static/test/index.test.js new file mode 100644 index 0000000000000..9ee69eba8d410 --- /dev/null +++ b/test/integration/errors-on-output-to-static/test/index.test.js @@ -0,0 +1,28 @@ +/* eslint-env jest */ + +import path from 'path' +import fs from 'fs-extra' +import { nextBuild, nextExport } from 'next-test-utils' + +jest.setTimeout(1000 * 60 * 1) +const appDir = path.join(__dirname, '..') +const nextConfig = path.join(appDir, 'next.config.js') + +describe('Errors on output to static', () => { + it('Throws error when export out dir is static', async () => { + await fs.remove(nextConfig) + await nextBuild(appDir) + const outdir = path.join(appDir, 'static') + const results = await nextExport( + appDir, + { outdir }, + { + stdout: true, + stderr: true, + } + ) + expect(results.stdout + results.stderr).toMatch( + /The 'static' directory is reserved in Next\.js and can not be used as/ + ) + }) +}) diff --git a/test/package-managers-tests/basic-pnpm/pages/about.js b/test/package-managers-tests/basic-pnpm/pages/about.js deleted file mode 100644 index 46817af02a5c1..0000000000000 --- a/test/package-managers-tests/basic-pnpm/pages/about.js +++ /dev/null @@ -1,3 +0,0 @@ -export default function About() { - return
About us
-} diff --git a/test/package-managers-tests/basic-pnpm/pages/about2.js b/test/package-managers-tests/basic-pnpm/pages/about2.js deleted file mode 100644 index 2b8fe3f38cba6..0000000000000 --- a/test/package-managers-tests/basic-pnpm/pages/about2.js +++ /dev/null @@ -1,3 +0,0 @@ -export default function About2() { - return
About 2
-} diff --git a/test/package-managers-tests/basic-pnpm/pages/day/index.js b/test/package-managers-tests/basic-pnpm/pages/day/index.js deleted file mode 100644 index a3cd64f29174d..0000000000000 --- a/test/package-managers-tests/basic-pnpm/pages/day/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export default function Day() { - return
Hello Day
-} diff --git a/test/package-managers-tests/basic-pnpm/pages/index.js b/test/package-managers-tests/basic-pnpm/pages/index.js deleted file mode 100644 index 7bb25eccba89e..0000000000000 --- a/test/package-managers-tests/basic-pnpm/pages/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import Link from 'next/link' -export default function Home() { - return ( -
- Hello World.{' '} - - About - -
- ) -} diff --git a/test/package-managers-tests/basic-pnpm/test/index.test.js b/test/package-managers-tests/basic-pnpm/test/index.test.js deleted file mode 100644 index f1340f8e06dff..0000000000000 --- a/test/package-managers-tests/basic-pnpm/test/index.test.js +++ /dev/null @@ -1,74 +0,0 @@ -/* eslint-env jest */ -import { execSync } from 'child_process' -import fs from 'fs-extra' -import path from 'path' - -jest.setTimeout(100 * 1000) - -beforeAll(async () => { - await clean() -}) - -afterAll(async () => { - await clean() -}) - -test('pnpm installs', async () => { - const pnpm = getStdout('yarn bin pnpm') - exec(pnpm + ' init -y') - exec(pnpm + ' add next react react-dom') - await useLocalNextjs() - // exec('pnpm install') -}) - -test('nextjs builds with pnpm', () => { - const pnpx = getStdout(`yarn bin pnpx`) - exec(pnpx + ' next build') -}) - -const exec = (cmd) => { - return execSync(cmd, { - env: process.env, - shell: true, - stdio: 'inherit', - cwd: path.resolve(__dirname, '..'), - }) -} - -const getStdout = (cmd) => { - return execSync(cmd, { - env: process.env, - shell: true, - stdio: 'pipe', - }) - .toString() - .trim() -} - -async function useLocalNextjs() { - // installed nextjs - const nextPath = path.dirname(require.resolve('next/package.json')) - - // repository root - const root = path.dirname( - require.resolve(path.resolve(process.cwd(), 'package.json')) - ) - - // local nextjs - const currentNextPath = path.resolve(root, 'packages/next') - - // copy local nextjs to node_modules - await fs.copy( - path.resolve(currentNextPath, 'dist'), - path.resolve(nextPath, 'dist') - ) - - console.log('copied local nextjs to node_modules') -} - -async function clean() { - // jest test cannot be found if a package.json exists in test directory - await fs.remove(path.resolve(__dirname, '../package.json')) - await fs.remove(path.resolve(__dirname, '../node_modules')) - await fs.remove(path.resolve(__dirname, '../pnpm-lock.yaml')) -} diff --git a/test/package-managers/pnpm/app/package.json b/test/package-managers/pnpm/app/package.json new file mode 100644 index 0000000000000..3cc6af9e7f671 --- /dev/null +++ b/test/package-managers/pnpm/app/package.json @@ -0,0 +1,14 @@ +{ + "name": "pnpm-app", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "react": "^16.7.0", + "react-dom": "^16.7.0" + } +} diff --git a/test/package-managers/pnpm/app/pages/index.js b/test/package-managers/pnpm/app/pages/index.js new file mode 100644 index 0000000000000..69192c68a0ce5 --- /dev/null +++ b/test/package-managers/pnpm/app/pages/index.js @@ -0,0 +1 @@ +export default () =>

Hello World

diff --git a/test/package-managers/pnpm/test/index.test.js b/test/package-managers/pnpm/test/index.test.js new file mode 100644 index 0000000000000..2a34123a3804b --- /dev/null +++ b/test/package-managers/pnpm/test/index.test.js @@ -0,0 +1,127 @@ +/* eslint-env jest */ +import execa from 'execa' +import fs from 'fs-extra' +import os from 'os' +import path from 'path' + +const pnpmExecutable = path.join( + __dirname, + '..', + '..', + '..', + '..', + 'node_modules', + '.bin', + 'pnpm' +) +const packagesDir = path.join(__dirname, '..', '..', '..', '..', 'packages') +const appDir = path.join(__dirname, '..', 'app') + +jest.setTimeout(1000 * 60 * 5) + +const runNpm = (cwd, ...args) => execa('npm', [...args], { cwd }) +const runPnpm = (cwd, ...args) => execa(pnpmExecutable, [...args], { cwd }) + +async function usingTempDir(fn) { + const folder = path.join(os.tmpdir(), Math.random().toString(36).substring(2)) + await fs.mkdirp(folder) + try { + return await fn(folder) + } finally { + await fs.remove(folder) + } +} + +/** + * Using 'npm pack', create a tarball of the given package in + * directory `pkg` and write it to `cwd`. + * + * `pkg` is relative to the monorepo 'packages/' directory. + * + * Return the absolute path to the tarball. + */ +async function pack(cwd, pkg) { + const pkgDir = path.join(packagesDir, pkg) + const { stdout } = await runNpm( + cwd, + 'pack', + '--ignore-scripts', // Skip the prepublish script + path.join(packagesDir, pkg) + ) + const tarballFilename = stdout.match(/.*\.tgz/)[0] + + if (!tarballFilename) { + throw new Error( + `pnpm failed to pack "next" package tarball in directory ${pkgDir}.` + ) + } + + return path.join(cwd, tarballFilename) +} + +describe('pnpm support', () => { + it('should build with dependencies installed via pnpm', async () => { + // Create a Next.js app in a temporary directory, and install dependencies with pnpm. + // + // "next" and its monorepo dependencies are installed by `npm pack`-ing tarballs from + // 'next.js/packages/*', because installing "next" directly via + // `pnpm add path/to/next.js/packages/next` results in a symlink: + // 'app/node_modules/next' -> 'path/to/next.js/packages/next'. + // This is undesired since modules inside "next" would be resolved to the + // next.js monorepo 'node_modules' and lead to false test results; + // installing from a tarball avoids this issue. + // + // The "next" package's monorepo dependencies (e.g. "@next/env", "@next/polyfill-module") + // are not bundled with `npm pack next.js/packages/next`, + // so they need to be packed individually. + // To ensure that they are installed upon installing "next", a package.json "pnpm.overrides" + // field is used to override these dependency paths at install time. + await usingTempDir(async (tempDir) => { + const nextTarballPath = await pack(tempDir, 'next') + const dependencyTarballPaths = { + '@next/env': await pack(tempDir, 'next-env'), + '@next/polyfill-module': await pack(tempDir, 'next-polyfill-module'), + '@next/react-dev-overlay': await pack(tempDir, 'react-dev-overlay'), + '@next/react-refresh-utils': await pack(tempDir, 'react-refresh-utils'), + } + + const tempAppDir = path.join(tempDir, 'app') + await fs.copy(appDir, tempAppDir) + + // Inject dependency tarball paths into a "pnpm.overrides" field in package.json, + // so that they are installed from packed tarballs rather than from the npm registry. + const packageJsonPath = path.join(tempAppDir, 'package.json') + const overrides = {} + for (const [dependency, tarballPath] of Object.entries( + dependencyTarballPaths + )) { + overrides[dependency] = `file:${tarballPath}` + } + const packageJsonWithOverrides = { + ...(await fs.readJson(packageJsonPath)), + pnpm: { overrides }, + } + await fs.writeFile( + packageJsonPath, + JSON.stringify(packageJsonWithOverrides, null, 2) + ) + + await runPnpm(tempAppDir, 'install') + await runPnpm(tempAppDir, 'add', nextTarballPath) + + expect( + await fs.pathExists(path.join(tempAppDir, 'pnpm-lock.yaml')) + ).toBeTruthy() + + const packageJson = await fs.readJson(packageJsonPath) + expect(packageJson.dependencies['next']).toMatch(/^file:/) + for (const dependency of Object.keys(dependencyTarballPaths)) { + expect(packageJson.pnpm.overrides[dependency]).toMatch(/^file:/) + } + + const { stdout, stderr } = await runPnpm(tempAppDir, 'run', 'build') + console.log(stdout, stderr) + expect(stdout).toMatch(/Compiled successfully/) + }) + }) +}) diff --git a/yarn.lock b/yarn.lock index 41600effcdf6d..dda54689a2d5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2944,12 +2944,6 @@ "@types/prop-types" "*" csstype "^2.2.0" -"@types/resolve@0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" - dependencies: - "@types/node" "*" - "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -11951,10 +11945,10 @@ pnp-webpack-plugin@1.6.4: dependencies: ts-pnp "^1.1.6" -pnpm@5.8.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/pnpm/-/pnpm-5.8.0.tgz#a933d6c756efe8795b12004bbff1b82c622e771b" - integrity sha512-J2rAxEXnohwcDkR4KNI6UsYhDs9hJ/tje/BahHpXawi406pmxd6caJUXfRxZPbKvKdyVqfBRKhlX1vyhYbM8lQ== +pnpm@5.14.3: + version "5.14.3" + resolved "https://registry.yarnpkg.com/pnpm/-/pnpm-5.14.3.tgz#88e53906652c85ba2e6f69294042d95aad018cbe" + integrity sha512-PFjHFWCsHgaNCpOwOAgN6H71PA8td8PnwSE1ArXz//OyfdfIwws1s23XLmokhHcnE3JsBSiIR3NOW8JZ5QcxlQ== posix-character-classes@^0.1.0: version "0.1.1" @@ -13655,13 +13649,6 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232" - integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw== - dependencies: - path-parse "^1.0.6" - resolve@1.17.0: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"