From fc98c13a2e6bc545073de0eedbe045352b387f6d Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Thu, 20 Aug 2020 12:05:29 -0400 Subject: [PATCH] Warn on duplicate Sass deps (#16398) Fixes #13953 --- errors/duplicate-sass.md | 33 +++++++++++++++++++ packages/next/cli/next-dev.ts | 12 +++++++ .../integration/cli/duplicate-sass/.gitignore | 1 + .../node_modules/node-sass/index.js | 1 + .../node_modules/node-sass/package.json | 4 +++ .../duplicate-sass/node_modules/sass/index.js | 1 + .../node_modules/sass/package.json | 4 +++ .../cli/duplicate-sass/package.json | 6 ++++ .../cli/duplicate-sass/pages/index.js | 3 ++ test/integration/cli/test/index.test.js | 17 ++++++++++ 10 files changed, 82 insertions(+) create mode 100644 errors/duplicate-sass.md create mode 100644 test/integration/cli/duplicate-sass/.gitignore create mode 100644 test/integration/cli/duplicate-sass/node_modules/node-sass/index.js create mode 100644 test/integration/cli/duplicate-sass/node_modules/node-sass/package.json create mode 100644 test/integration/cli/duplicate-sass/node_modules/sass/index.js create mode 100644 test/integration/cli/duplicate-sass/node_modules/sass/package.json create mode 100644 test/integration/cli/duplicate-sass/package.json create mode 100644 test/integration/cli/duplicate-sass/pages/index.js diff --git a/errors/duplicate-sass.md b/errors/duplicate-sass.md new file mode 100644 index 0000000000000..aa4e6e9b8b39d --- /dev/null +++ b/errors/duplicate-sass.md @@ -0,0 +1,33 @@ +# Duplicate Sass Dependencies + +#### Why This Error Occurred + +Your project has a direct dependency on both `sass` and `node-sass`, two +different package that both compile Sass files! + +Next.js will only use one of these, so it is suggested you remove one or the +other. + +#### Possible Ways to Fix It + +The `sass` package is a modern implementation of Sass in JavaScript that +supports all the new features and does not require any native dependencies. + +Since `sass` is now the canonical implementation, we suggest removing the older +`node-sass` package, which should speed up your builds and project install time. + +**Via npm** + +```bash +npm uninstall node-sass +``` + +**Via Yarn** + +```bash +yarn remove node-sass +``` + +### Useful Links + +- [`sass` package documentation](https://github.com/sass/dart-sass) diff --git a/packages/next/cli/next-dev.ts b/packages/next/cli/next-dev.ts index ed044bbd1b521..53fa86d444949 100755 --- a/packages/next/cli/next-dev.ts +++ b/packages/next/cli/next-dev.ts @@ -91,6 +91,18 @@ const nextDev: cliCommand = (argv) => { ) } } + + const [sassVersion, nodeSassVersion] = await Promise.all([ + getPackageVersion({ cwd: dir, name: 'sass' }), + getPackageVersion({ cwd: dir, name: 'node-sass' }), + ]) + if (sassVersion && nodeSassVersion) { + Log.warn( + 'Your project has both `sass` and `node-sass` installed as dependencies, but should only use one or the other. ' + + 'Please remove the `node-sass` dependency from your project. ' + + ' Read more: https://err.sh/next.js/duplicate-sass' + ) + } } const port = args['--port'] || 3000 diff --git a/test/integration/cli/duplicate-sass/.gitignore b/test/integration/cli/duplicate-sass/.gitignore new file mode 100644 index 0000000000000..cf4bab9ddde9f --- /dev/null +++ b/test/integration/cli/duplicate-sass/.gitignore @@ -0,0 +1 @@ +!node_modules diff --git a/test/integration/cli/duplicate-sass/node_modules/node-sass/index.js b/test/integration/cli/duplicate-sass/node_modules/node-sass/index.js new file mode 100644 index 0000000000000..4ba52ba2c8df6 --- /dev/null +++ b/test/integration/cli/duplicate-sass/node_modules/node-sass/index.js @@ -0,0 +1 @@ +module.exports = {} diff --git a/test/integration/cli/duplicate-sass/node_modules/node-sass/package.json b/test/integration/cli/duplicate-sass/node_modules/node-sass/package.json new file mode 100644 index 0000000000000..9145e5f2ca90f --- /dev/null +++ b/test/integration/cli/duplicate-sass/node_modules/node-sass/package.json @@ -0,0 +1,4 @@ +{ + "name": "node-sass", + "version": "1.0.0" +} diff --git a/test/integration/cli/duplicate-sass/node_modules/sass/index.js b/test/integration/cli/duplicate-sass/node_modules/sass/index.js new file mode 100644 index 0000000000000..4ba52ba2c8df6 --- /dev/null +++ b/test/integration/cli/duplicate-sass/node_modules/sass/index.js @@ -0,0 +1 @@ +module.exports = {} diff --git a/test/integration/cli/duplicate-sass/node_modules/sass/package.json b/test/integration/cli/duplicate-sass/node_modules/sass/package.json new file mode 100644 index 0000000000000..629a9ea43446f --- /dev/null +++ b/test/integration/cli/duplicate-sass/node_modules/sass/package.json @@ -0,0 +1,4 @@ +{ + "name": "sass", + "version": "1.0.0" +} diff --git a/test/integration/cli/duplicate-sass/package.json b/test/integration/cli/duplicate-sass/package.json new file mode 100644 index 0000000000000..f4f88ddfadea4 --- /dev/null +++ b/test/integration/cli/duplicate-sass/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "node-sass": "*", + "sass": "*" + } +} diff --git a/test/integration/cli/duplicate-sass/pages/index.js b/test/integration/cli/duplicate-sass/pages/index.js new file mode 100644 index 0000000000000..8f6a8e1b41548 --- /dev/null +++ b/test/integration/cli/duplicate-sass/pages/index.js @@ -0,0 +1,3 @@ +export default function Home() { + return

Hello

+} diff --git a/test/integration/cli/test/index.test.js b/test/integration/cli/test/index.test.js index 9dd7a1dcd87d6..1c03e39552548 100644 --- a/test/integration/cli/test/index.test.js +++ b/test/integration/cli/test/index.test.js @@ -18,6 +18,7 @@ const dirOldReact = join(__dirname, '../old-react') const dirOldReactDom = join(__dirname, '../old-react-dom') const dirExperimentalReact = join(__dirname, '../experimental-react') const dirExperimentalReactDom = join(__dirname, '../experimental-react-dom') +const dirDuplicateSass = join(__dirname, '../duplicate-sass') describe('CLI Usage', () => { describe('no command', () => { @@ -295,6 +296,22 @@ describe('CLI Usage', () => { await killApp(instance) }) + + test('duplicate sass deps', async () => { + const port = await findPort() + + let stderr = '' + let instance = await launchApp(dirDuplicateSass, port, { + stderr: true, + onStderr(msg) { + stderr += msg + }, + }) + + expect(stderr).toMatch('both `sass` and `node-sass` installed') + + await killApp(instance) + }) }) describe('export', () => {