From 36295e5fc0c1dca02dc251d234d88a245aafecc2 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 11 Mar 2020 12:21:34 -0400 Subject: [PATCH 1/3] Improve Sass Error --- errors/install-sass.md | 19 +++++++++++++++++++ .../error-overlay/format-webpack-messages.js | 17 ++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 errors/install-sass.md diff --git a/errors/install-sass.md b/errors/install-sass.md new file mode 100644 index 000000000000000..91b7d1301f39562 --- /dev/null +++ b/errors/install-sass.md @@ -0,0 +1,19 @@ +# Install `sass` to Use Built-In Sass Support + +#### Why This Error Occurred + +Using Next.js' [built-in Sass support](https://nextjs.org/docs/basic-features/built-in-css-support#sass-support) requires that you bring your own version of Sass. + +#### Possible Ways to Fix It + +Please install the `sass` package in your project. + +```bash +npm i sass +# or +yarn add sass +``` + +### Useful Links + +- [Sass Support in Documentation](https://nextjs.org/docs/basic-features/built-in-css-support#sass-support) diff --git a/packages/next/client/dev/error-overlay/format-webpack-messages.js b/packages/next/client/dev/error-overlay/format-webpack-messages.js index 6ff01edca15be6e..c61845352ff6abb 100644 --- a/packages/next/client/dev/error-overlay/format-webpack-messages.js +++ b/packages/next/client/dev/error-overlay/format-webpack-messages.js @@ -31,8 +31,7 @@ function isLikelyASyntaxError(message) { } // Cleans up webpack error messages. -// eslint-disable-next-line no-unused-vars -function formatMessage(message, isError) { +function formatMessage(message) { let lines = message.split('\n') // Strip Webpack-added headers off errors/warnings @@ -58,9 +57,6 @@ function formatMessage(message, isError) { /SyntaxError\s+\((\d+):(\d+)\)\s*(.+?)\n/g, `${friendlySyntaxErrorLabel} $3 ($1:$2)\n` ) - // Remove columns from ESLint formatter output (we added these for more - // accurate syntax errors) - message = message.replace(/Line (\d+):\d+:/g, 'Line $1:') // Clean up export errors message = message.replace( /^.*export '(.+?)' was not found in '(.+?)'.*$/gm, @@ -93,6 +89,17 @@ function formatMessage(message, isError) { ] } + // Add helpful message for users trying to use Sass for the first time + if (lines[1] && lines[1].match(/Cannot find module.+node-sass/)) { + // ./file.module.scss (<>) => ./file.module.scss + lines[0] = lines[0].replace(/(.+) \(.+?(?=\?\?).+?\)/, '$1') + + lines[1] = + "To use Next.js' built-in Sass support, you first need to install `sass`.\n" + lines[1] += 'Run `npm i sass` or `yarn add sass` inside your workspace.\n' + lines[1] += '\nLearn more: https://err.sh/next.js/install-sass' + } + message = lines.join('\n') // Internal stacks are generally useless so we strip them... with the // exception of stacks containing `webpack:` because they're normally From 03aa6218f9b290a447ca497cb0aec4f116031eb3 Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 11 Mar 2020 16:05:07 -0400 Subject: [PATCH 2/3] test sass error massage --- .../scss-fixtures/webpack-error/mock.js | 7 ++++ .../scss-fixtures/webpack-error/pages/_app.js | 12 ++++++ .../webpack-error/pages/index.js | 3 ++ .../webpack-error/styles/global.scss | 4 ++ test/integration/scss/test/index.test.js | 40 ++++++++++++++++--- 5 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 test/integration/scss-fixtures/webpack-error/mock.js create mode 100644 test/integration/scss-fixtures/webpack-error/pages/_app.js create mode 100644 test/integration/scss-fixtures/webpack-error/pages/index.js create mode 100644 test/integration/scss-fixtures/webpack-error/styles/global.scss diff --git a/test/integration/scss-fixtures/webpack-error/mock.js b/test/integration/scss-fixtures/webpack-error/mock.js new file mode 100644 index 000000000000000..2b56e6dc476c766 --- /dev/null +++ b/test/integration/scss-fixtures/webpack-error/mock.js @@ -0,0 +1,7 @@ +let originalLoader +const M = require('module') +originalLoader = M._load +M._load = function hookedLoader(request, parent, isMain) { + if (request === 'node-sass') request = 'node-sass-begone' + return originalLoader(request, parent, isMain) +} diff --git a/test/integration/scss-fixtures/webpack-error/pages/_app.js b/test/integration/scss-fixtures/webpack-error/pages/_app.js new file mode 100644 index 000000000000000..b89fe16feb73145 --- /dev/null +++ b/test/integration/scss-fixtures/webpack-error/pages/_app.js @@ -0,0 +1,12 @@ +import React from 'react' +import App from 'next/app' +import '../styles/global.scss' + +class MyApp extends App { + render() { + const { Component, pageProps } = this.props + return + } +} + +export default MyApp diff --git a/test/integration/scss-fixtures/webpack-error/pages/index.js b/test/integration/scss-fixtures/webpack-error/pages/index.js new file mode 100644 index 000000000000000..5cbac8a153d77f0 --- /dev/null +++ b/test/integration/scss-fixtures/webpack-error/pages/index.js @@ -0,0 +1,3 @@ +export default function Home() { + return
This text should be red.
+} diff --git a/test/integration/scss-fixtures/webpack-error/styles/global.scss b/test/integration/scss-fixtures/webpack-error/styles/global.scss new file mode 100644 index 000000000000000..da7b3d1417b1bba --- /dev/null +++ b/test/integration/scss-fixtures/webpack-error/styles/global.scss @@ -0,0 +1,4 @@ +$var: red; +.red-text { + color: $var; +} diff --git a/test/integration/scss/test/index.test.js b/test/integration/scss/test/index.test.js index 5a75663ce8235c1..d47dcce6687264b 100644 --- a/test/integration/scss/test/index.test.js +++ b/test/integration/scss/test/index.test.js @@ -1,26 +1,54 @@ /* eslint-env jest */ /* global jasmine */ +import cheerio from 'cheerio' import 'flat-map-polyfill' -import { join } from 'path' import { readdir, readFile, remove } from 'fs-extra' import { + File, findPort, + killApp, + launchApp, nextBuild, nextStart, - launchApp, - killApp, - File, - waitFor, renderViaHTTP, + waitFor, } from 'next-test-utils' import webdriver from 'next-webdriver' -import cheerio from 'cheerio' +import { join } from 'path' jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2 const fixturesDir = join(__dirname, '../..', 'scss-fixtures') describe('SCSS Support', () => { + describe('Friendly Webpack Error', () => { + const appDir = join(fixturesDir, 'webpack-error') + + const mockFile = join(appDir, 'mock.js') + + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) + + it('should be a friendly error successfully', async () => { + const { code, stderr } = await nextBuild(appDir, [], { + env: { NODE_OPTIONS: `--require ${mockFile}` }, + stderr: true, + }) + expect(code).toBe(1) + expect(stderr.split('Require stack:')[0]).toMatchInlineSnapshot(` + "Failed to compile. + + ./styles/global.scss + To use Next.js' built-in Sass support, you first need to install \`sass\`. + Run \`npm i sass\` or \`yarn add sass\` inside your workspace. + + Learn more: https://err.sh/next.js/install-sass + " + `) + }) + }) + describe('Basic Global Support', () => { const appDir = join(fixturesDir, 'single-global') From bbdfdc582aad5604dbf0e402cd9b73cf6920e14a Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 11 Mar 2020 16:09:53 -0400 Subject: [PATCH 3/3] use quotes --- test/integration/scss/test/index.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/integration/scss/test/index.test.js b/test/integration/scss/test/index.test.js index d47dcce6687264b..1678bb00e07962d 100644 --- a/test/integration/scss/test/index.test.js +++ b/test/integration/scss/test/index.test.js @@ -15,6 +15,7 @@ import { } from 'next-test-utils' import webdriver from 'next-webdriver' import { join } from 'path' +import { quote as shellQuote } from 'shell-quote' jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2 @@ -32,7 +33,7 @@ describe('SCSS Support', () => { it('should be a friendly error successfully', async () => { const { code, stderr } = await nextBuild(appDir, [], { - env: { NODE_OPTIONS: `--require ${mockFile}` }, + env: { NODE_OPTIONS: shellQuote([`--require`, mockFile]) }, stderr: true, }) expect(code).toBe(1)