How is ESLint integrated into Create React App? - javascript

When I run npx create-react-app ..., a bare-bone React project is being created for me.
When I then peek into package.json, there seems to be some evidence of ESLint to be present, as there is this:
"eslintConfig": {
"extends": "react-app"
},
However, whenever I install ESLint as a dev dependency and configure it -- as I usually do --, VS Code seems to pick it up.
In this case, VS Code does not seem to recognize that there is any kind of linter present/configured.
This is not super surprising, as ESLint is not a dependency of the React project I just generated -- at least not according to package.json.
When I try to run eslint . within the project's root directory, it says "command not found".
I tried to breathe life into this ESLint configuration by expanding it, so now I have this:
"eslintConfig": {
"extends": ["react-app", "eslint:recommended", "google"],
"rules": {
"semi": ["error", "always"],
"quotes": ["error", "double"]
}
},
This changes nothing.
I manipulated the source code in a way that I know it violates the above configuration, yet, I have not been signaled any wrongdoing.
This leads me to a simple question:
Do projects generated by create-react-app come with some kind of ESLint configuration, and, if so, how do I enable and extend it correctly?
As I am being referred to the number one Google hit that comes up when searching "create react app eslint" -- which I have obviously read --, let me clarify what I mean:
ESLint is obviously integrated into Create React App in a different way than it would be if it had been manually added to the project using like so.
This is not only evident by the sheer number of people who post about their struggles of getting the two to work together.
This is also evident as...
...one cannot run the eslint command in the project root.
...ESLint does not seem to be a dependency within package.json.
...VS Code doesn't pick up that there is ESLint present.
...there is no .eslintrc.* file in the project root.
...etc.
So: How do I go about ESLint in the context of Create React App? For starters: How do I run it? How do I expand it? And why does VS Code not pick it up -- even though it usually notices the presence of ESLint?

Yes, create-react-app comes with eslint config.
How do I enable and extend it correctly?
You can check how to extend it here.
{
"eslintConfig": {
"extends": ["react-app", "shared-config"],
"rules": {
"additional-rule": "warn"
},
"overrides": [
{
"files": ["**/*.ts?(x)"],
"rules": {
"additional-typescript-only-rule": "warn"
}
}
]
}
}
How do I enable it?
You need to integrate it with your IDE.
How do I run it?
After integrating it, an eslint server will be running in the background and will enable linting for your IDE (sometimes restarting IDE required).
I checked all your claims after running npx create-react-app example:
...one cannot run the eslint command in the project root.
You can:
eslint is installed as part of the project dependency, just by running eslint globally (eslint [cmd]) you need to ensure it installed globally (not recommended).
...ESLint does not seem to be a dependency within package.json.
Why should it be? That's why you using a starter like CRA. It's an inner dependency, you don't need to worry about it, that's CRA's job.
...VS Code doesn't pick up that there is ESLint present.
It does, check the OUTPUT tab and look for ESLint to see the server's output.
...there is no .eslintrc.* file in the project root.
You get the default configuration from CRA (which is hidden from you for focusing on coding).
Add such file if you want to override it (you can also extend it, check the docs).
Its very useful to understand what eslint actually is and how we use it React development, check out related question "Do React hooks really have to start with “use”?".

To expand on the top comment's answer:
...ESLint does not seem to be a dependency within package.json.
Why should it be? That's why you using a starter like CRA. It's an inner dependency, you don't need to worry about it, that's CRA's job.
A project created with create-react-app will have react-scripts as a dependency.
react-scripts has eslint installed as a dependency, as seen in react-scripts package.json.
You can see if a package is installed (and where) by running npm ls <package> in your project root.
npm ls eslint shows:
└─┬ react-scripts#4.0.3
└── eslint#7.21.0
This shows the dependency tree that we manually investigated by looking in GitHub at react-scripts.
So - a project made with create-react-app does come with eslint. As it is a dependency, not something globally installed, then it must be ran with a npm script.
This is why running eslint . in your terminal does not work, but using
"lint": "eslint .",
then npm run lint does. (though you may with to make the command eslint --ignore-path .gitignore . due to a current bug).
Similarly, the eslint configs are installed in react-scripts, then referenced in the default project output's own package.json.

Every Create React App depends on ESLint via react-scripts
I believe I have answered most of your questions in the Sections
below.
Here is a summary.
Do projects generated by create-react-app come with some kind of
ESLint configuration?
– Yes, ESLint gets installed and configured.
(Section 1 below.)
How do I enable and extend it correctly?
– It is already enabled. You expand it exactly as you already suggested
in the question, except that you don't need to change anything under
the extends attribute.
(Sections 1 & 2 below.)
ESLint is obviously integrated into Create React App in a different
way than it would be if it had been manually added to the project
using
[npm install eslint --save-dev and npm init #eslint/config ?]
– No, it's not.
Installing ESLint once again
(npm install eslint --save-dev) does add
  "devDependencies": {
    "eslint": "^7.32.0"
  }
to package.json.
But that's all it does.
The practical implications are none, because "eslint": "^7.32.0" is
already installed as a dependency via react-scripts.
I advise against running npm init #eslint/config, which is
a command that creates a .eslintrc.* configuration file.
If you do run this command, consider moving all the contents of
.eslintrc.* to package.json under eslintConfig.
Then delete the problematic .eslintrc.* file.
It might save you a lot of pain.
1
(Sections 1 & 5 below.)
one cannot run the eslint command in the project root [?]
– Yes, you can!
It's npx eslint . --ext .js
(Section 4 below.)
ESLint does not seem to be a dependency within package.json [?]
– Yes, it is!
The dependency is indirect as react-scripts depends
on ESLint and on a lot of other packages.
(Section 1 below.)
VS Code doesn't pick up that there is ESLint present [?]
– Yes, it does! Run npx eslint . --ext .js.
If you get at least one warning or error, then you know you should see
it in VS Code as well.
(Section 3 below – check out the gotchas.)
there is no .eslintrc.* file in the project root.
– Be glad there isn't! And don't put one there either!
(Section 5 below.)
0. Prerequisites
In order to be able to answer your questions, I created an App :
2
npx create-react-app how-is-eslint-integrated-into-create-react-app
I then deleted all files in the src subdirectory, and inserted my own
versions of App.js, App.css, index.js, index.css, along with
a components subdirectory that contains a Button component.
In package.json I deleted a few irrelevant lines, such as
"version": "0.1.0",
and "private": true, and the production attribute
under browserslist.
The resulting package.json :
{
"name": "how-is-eslint-integrated-into-create-react-app",
"dependencies": {
"#testing-library/jest-dom": "^5.16.2",
"#testing-library/react": "^12.1.3",
"#testing-library/user-event": "^13.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"development": [
"last 1 chrome version"
]
}
}
When you wrote your question a little more than two years ago,
the eslintConfig attribute was
,
"eslintConfig": {
"extends": "react-app"
}
whereas nowadays, it's
,
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
}
I will assume that this change makes no difference for the issues and
questions you bring up
(unless someone proves me wrong).
Another difference over the past two years – apart from the obvious
changes in version numbering – is the added web-vitals attribute :
,
"web-vitals": "^2.1.4"
which is a package for measuring performance metrics in JavaScript.
3
Thus, web-vitals is irrelevant for your questions.
You can download the resulting
zip file containing all necessary project files.
Once downloaded – from the root of the project (directory Q59633005)
– run npm install.
Expect it to take anytime between 4 and 11 minutes to complete.
Next run npm start.
Expect your default web browser to open and
– after hitting F12 – display :
4
Now close the server from the terminal by hitting
Ctrl+C.
Take a look inside App.js. The contents are :
// App.js
import React, { useCallback, useState } from 'react';
import "./App.css";
import Button from "./components/UI/Button/Button"
function App(unUsedArgument) {
const [unUsedVariable, setShowParagraph] = useState(true);
const showParagraphFcn = useCallback(() => {
setShowParagraph((prevToggle) => !prevToggle);
},[]);
console.log("App RUNNING");
return (
<div className="app">
<h1>Hi there!</h1>
<Button onClick={showParagraphFcn}>A Button</Button>
</div>
);
}
export default App;
I now have project to help answer your questions.
1. ESLint in Visual Studio Code
VS Code does not seem to recognize that there is any kind of linter
present/configured.
This is not super surprising, as ESLint is not a dependency of the
React project I just generated -- at least not according to
package.json.
The npx create-react-app ... does indeed install ESLint.
ESLint is deeply buried in the dependency tree of the react-scripts
package.
The top node for ESLint in react-scripts is eslint-config-react-app.
5
Some basic configuration is also part of the deal.
So ESLint does work out of the box.
VS Code shows a warning for unUsedVariable on line 7 of App.js
(but for some reason not for unUsedArgument on line 6).
In VS Code, expect to see :
2. How to expand ESLint
How do I expand [ESLint in a Create React App]?
To expand ESLint, you need to add rules under eslintConfig in
package.json, exactly as you have already suggested in your
question.
To try your example, replace
,
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
}
with
,
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
],
"rules": {
"semi": [
"error",
"always"
],
"quotes": [
"error",
"double"
]
}
}
After restarting VS Code, it still shows the warning for
unUsedVariable on line 7, but now also an error on line 2 for having
single quotes instead of double quotes, and an error on line 4 for the
missing semicolon at the end of the line.
This shows that you have already correctly answered how to expand
Create React App.
For another example, consider looking at the
package.json | eslintConfig of this answer.
3. Some gotchas with VS Code
Still don't see the errors and warnings as in the screenshot
above?
It might not work, I know.
Three gotchas to check :
You must install the VS Code ESLint extension.
After you have made any changes to package.json, you must close
and restart VS Code.
Then wait at least 60-100 seconds (or even 2 minutes) before
you conclude it didn't work.
Add "eslint.nodePath": "C:\\Program Files\\nodejs", to
settings.json in VS Code.
4. A much faster way to check if ESLint works
For starters: How do I run it?
Answer:
6
npx eslint . --ext .js
The first four lines of the response:
C:\stackexchange\stackoverflow\linting\eslint\Q59633005\src\App.js
2:46 error Strings must use doublequote quotes
4:51 error Missing semicolon semi
7:10 warning 'unUsedVariable' is assigned a value but never used no-unused-vars
– In less than 10 seconds, you get the same information about errors
and warnings as in VS Code.
5. A word of warning
If you don't like hard-to-debug errors such as
Parsing error: The keyword 'import' is reserved
then don't use any .eslintrc.* files at all.
1
In my experience, you can put all ESLint configurations under
eslintConfig in package.json as described in Section 2 above.
– You won't need any .eslintrc.* files.
References
Every Create React App depends on ESLint via react-scripts
Long answer to Parsing error: The keyword 'import' is reserved
Short answer to Parsing error: The keyword 'import' is reserved
Zip file containing the needed project files
NPMGraph - Visualize NPM Module Dependencies
Post containing package.json – another eslintConfig example
VS Code ESLint extension
In VS Code, add "eslint.nodePath": "C:\\Program Files\\nodejs",
to settings.json
Parsing error: The keyword 'import' is reserved
1
If you want to know why, compare this long answer with
this short answer.
2 I'm on Windows 10, but I expect all the commands
provided here to work just as fine on both Linux and macOS – except
where otherwise stated.
3 You can find that out by running npm ll.
4 I use Google Chrome Version 98.0.4758.102, 64-bit.
Running on Windows 10.
5 I got this information from
NPMGraph - Visualize NPM Module Dependencies.
6 Alternatively, use the first line below if you are on
Microsoft Windows (backslashes).
Use the second line if you are on Linux or macOS (forward slashes).
node*modules\.bin\eslint . --ext .js
node*modules/.bin/eslint . --ext .js

your question makes perfect sense. I found that this works:
run ESLint in VS Code with 'npx eslint' (shows all the options) or also 'npx eslint .'
add a script to package.json "lint": "eslint ." and then use 'npm run lint'
I did not have a problem with integrating ESLint to VS Code. After installing VS Code extension for ESLint, I automatically see the warnings/errors in VS Code under Problems.

Related

How to import shared typescript code using create-react-app (no eject)?

I'm trying to achieve TypeScript code sharing in a create-react-app in non-eject mode, but I'm running into the infamous restriction that imports outside of src are not allowed:
You attempted to import ../../common/src/lib.ts which falls outside of the project src/ directory. [...]
For the non-TypeScript case this has been asked & answered here, but I can't get any of the solutions to work with TypeScript. Specifically the issues with the proposed solutions are:
Setting baseDir in ts-config.json: Here create-react-app complains about: Your project's baseUrl can only be set to src or node_modules. Create React App does not support other values at this time.
Approaches based on react-app-rewired: More promising. Disabling the ModuleScopePlugin gets me past the "attempted import outside src" error, but the problem now is that the loader of typescript files doesn't play along:
I have verified that the .ts itself is fine: Copying to ./src and importing it from there works fine.
I have also added ../../common/src folder to the includes list in ts-config.json.
My guess is that somehow the webpack loader configuration has a rule that prevents the TypeScript loader to transpile files that don't match its expected path patterns. How can this be fixed using react-app-rewired?
Symlinking sources doesn't work either -- again with the same problem. Probably because webpack internally resolves the symlinks and sees the file in a path where the normal loader rules don't apply.
Eject based solutions: I'd like not to eject for now, but I tried and I'm basically running into the same problem again.
I've also found other questions that sounded related but didn't answer the problem:
Create React App + Typescript In monorepo code sharing: Sounds basically like the same question, but it is not, because it is asking for the case of an ejected React app.
Sharing code between projects using TypeScript and webpack: Also addresses the code sharing problem, but not create-react-app specific, and I don't know if the solution can be transferred to create-react-app, because it requires manual webpack config control.
Re-using TypeScript typings in a mono repo seems to be a fairly reasonable pattern. Am I missing something or why is the create-react-app making this so difficult?
To reproduce: My code is basically 100% what you get from
npx create-react-app my-app --template typescript
with one import to external added.
You could use craco (create-react-app config override) to override the webpack config (abstracted as part of CRA) without ejecting.
Additionally you could use ts-loader to reference non-transpiled ts code directly in external projects (e.g. if you wanted to reference/use shared code/lib as part of a mono-repo).
Assuming your CRA app is in the client directory your project structure is like the following:
client/
|--src/
|--package.json
shared/
|--package.json
|--(ts files)
package.json
cd client
yarn add -D #craco/craco ts-loader
create a craco.config.js file in the client/ (CRA) directory
ensure the craco.config.js has the following content
const path = require("path");
module.exports = {
webpack: {
configure: webpackConfig => {
// ts-loader is required to reference external typescript projects/files (non-transpiled)
webpackConfig.module.rules.push({
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
transpileOnly: true,
configFile: 'tsconfig.json',
},
})
return webpackConfig;
}
}
};
Replace react-scripts commands in client/package.json with craco
/* client/package.json */
"scripts": {
- "start": "react-scripts start",
+ "start": "craco start",
- "build": "react-scripts build",
+ "build": "craco build"
- "test": "react-scripts test",
+ "test": "craco test"
}
UPDATE: Since react-app-rewired is only maintained passively and doesn't support CRA versions 2+ (we are are three major versions later at the time of writing), I would no longer recommend this approach.
After more hours of experimenting and reading up on GitHub issues, I finally have a working solution. Big thanks to BirukDmitry who made this very helpful post on GitHub. Step-by-step guide:
Install react-app-rewired and customize-cra
npm i react-app-rewired customize-cra --save-dev
Configure react-app-rewird with a minimal config-overrides.js like this:
const { removeModuleScopePlugin, override, babelInclude } = require("customize-cra");
const path = require("path");
module.exports = override(
removeModuleScopePlugin(), // (1)
babelInclude([
path.resolve("src"),
path.resolve("../common/src"), // (2)
])
);
Setting (1) is similar to what is needed for getting around the import-outside-src limitation in general (see linked question).
Setting (2) is crucial though to enabled babel-transpilation (and thus, including TS type stripping I presume) for other paths as well. This is where you have to put add your paths from which you want to import.
No adaptations needed for tsconfig.json.
Import using relative paths, e.g., import * as mymodule from '../../common/src/mymodule'.
#bluenote10 solution did the trick!
There was only one issue in step #2 that prevents Babel from transpilling ts files from ../../common/src
That is modified version of #bluenote10's code (that finally worked for me)
Install react-app-rewired and customize-cra
npm i react-app-rewired customize-cra --save-dev
Configure react-app-rewird with a minimal config-overrides.js like this:
const { removeModuleScopePlugin, override, babelInclude } = require("customize-cra");
const path = require("path");
module.exports = function (config, env) {
return Object.assign( // We need Object.assign() to not to loose initial config
config,
override(
removeModuleScopePlugin(), //1
babelInclude([
path.resolve('src'),
path.resolve('../common/src'), //2
])
)(config, env)
)
}
Setting (1) is similar to what is needed for getting around the import-outside-src limitation in general (see linked question).
Setting (2) is crucial though to enabled babel-transpilation (and thus, including TS type stripping I presume) for other paths as well. This is where you have to put add your paths from which you want to import.
No adaptations needed for tsconfig.json.
Import using relative paths, e.g., import * as mymodule from '../../common/src/mymodule'.
The alias solution for craco or rewired create-react-app is react-app-alias for systems as: craco, react-app-rewired, customize-cra
According docs of mentioned systems replace react-scripts in package.json and configure next:
react-app-rewired
// config-overrides.js
const {aliasWebpack, aliasJest} = require('react-app-alias')
const options = {} // default is empty for most cases
module.exports = aliasWebpack(options)
module.exports.jest = aliasJest(options)
craco
// craco.config.js
const {CracoAliasPlugin} = require('react-app-alias')
module.exports = {
plugins: [
{
plugin: CracoAliasPlugin,
options: {}
}
]
}
all
Configure aliases in json like this:
// tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"example/*": ["example/src/*"],
"#library/*": ["library/src/*"]
}
}
}
And add this file in extends section of main typescript config file:
// tsconfig.json
{
"extends": "./tsconfig.paths.json",
// ...
}
question where does ../../common/src/mymodule lives at ?
is it another project ?
If it is another project why dont you link'em
inside common code project run npm link
inside the project that will use the common code: npm link common-project
If there are not two different projects. why does it has to be outside of src ?
The link you posted The create-react-app imports restriction outside of src directory
and your case/problem are two totally different thing, plus they be tripping so hard. let me give you and idea of that problem and yours.
As we already know CRA creates a SPA single page app. which means that there is only one single html file. everything happens at the index.html which is located at <project>/public/index.html. If we compile the code we'll notice something the end bundle might look some like this
build
--static
----js
----css
----media
--index.html
--...more hashed crap...
public
src
and by default process.env.PUBLIC_URL is set to "/"
WHAT?? 🤨 yes look let me show you. there is an old say a picture explains more than 1000 words.
if we look at the image that according to its path it is located at ./src/styles/imageSlack.jpg or some.
So what if we console.log it.
WHAAAT!! where they do that at ? one thing you can do to test my theory is if you console.log(process.env.PUBLIC_URL) any where in yow code. now here is the big diference between this and that.
Browsers natively do not know Typescript.
So either you set yow code inside src and we end happy or
follow the separate of concerns principle and we create an npm package with the shared code and just imported as any other module.

SyntaxError: Cannot use import statement outside a module

I've got an ApolloServer project that's giving me trouble, so I thought I might update it and ran into issues when using the latest Babel. My "index.js" is:
require('dotenv').config()
import {startServer} from './server'
startServer()
And when I run it I get the error
SyntaxError: Cannot use import statement outside a module
First I tried doing things to convince TPTB* that this was a module (with no success). So I changed the "import" to a "require" and this worked.
But now I have about two dozen "imports" in other files giving me the same error.
*I'm sure the root of my problem is that I'm not even sure what's complaining about the issue. I sort of assumed it was Babel 7 (since I'm coming from Babel 6 and I had to change the presets) but I'm not 100% sure.
Most of what I've found for solutions don't seem to apply to straight Node. Like this one here:
ES6 module Import giving "Uncaught SyntaxError: Unexpected identifier"
Says it was resolved by adding "type=module" but this would typically go in the HTML, of which I have none. I've also tried using my project's old presets:
"presets": ["es2015", "stage-2"],
"plugins": []
But that gets me another error: "Error: Plugin/Preset files are not allowed to export objects, only functions."
Here are the dependencies I started with:
"dependencies": {
"#babel/polyfill": "^7.6.0",
"apollo-link-error": "^1.1.12",
"apollo-link-http": "^1.5.16",
"apollo-server": "^2.9.6",
"babel-preset-es2015": "^6.24.1",
Verify that you have the latest version of Node.js installed (or, at least 13.2.0+). Then do one of the following, as described in the documentation:
Option 1
In the nearest parent package.json file, add the top-level "type" field with a value of "module". This will ensure that all .js and .mjs files are interpreted as ES modules. You can interpret individual files as CommonJS by using the .cjs extension.
// package.json
{
"type": "module"
}
Option 2
Explicitly name files with the .mjs extension. All other files, such as .js will be interpreted as CommonJS, which is the default if type is not defined in package.json.
If anyone is running into this issue with TypeScript, the key to solving it for me was changing
"target": "esnext",
"module": "esnext",
to
"target": "esnext",
"module": "commonjs",
In my tsconfig.json. I was under the impression "esnext" was the "best", but that was just a mistake.
For those who were as confused as I was when reading the answers, in your package.json file, add
"type": "module"
in the upper level as show below:
{
"name": "my-app",
"version": "0.0.0",
"type": "module",
"scripts": { ...
},
...
}
According to the official documentation:
import statements are permitted only in ES modules. For similar functionality in CommonJS, see import().
To make Node.js treat your file as an ES module, you need to (Enabling):
add "type": "module" to package.json
add "--experimental-modules" flag to the Node.js call
I ran into the same issue and it's even worse: I needed both "import" and "require"
Some newer ES6 modules works only with import.
Some CommonJS works with require.
Here is what worked for me:
Turn your js file into .mjs as suggested in other answers
"require" is not defined with the ES6 module, so you can define it this way:
import { createRequire } from 'module'
const require = createRequire(import.meta.url);
Now 'require' can be used in the usual way.
Use import for ES6 modules and require for CommonJS.
Some useful links: Node.js's own documentation. difference between import and require. Mozilla has some nice documentation about import
I had the same issue and the following has fixed it (using Node.js 12.13.1):
Change .js files extension to .mjs
Add --experimental-modules flag upon running your app.
Optional: add "type": "module" in your package.json
More information: https://nodejs.org/api/esm.html
First we'll install #babel/cli, #babel/core and #babel/preset-env:
npm install --save-dev #babel/cli #babel/core #babel/preset-env
Then we'll create a .babelrc file for configuring Babel:
touch .babelrc
This will host any options we might want to configure Babel with:
{
"presets": ["#babel/preset-env"]
}
With recent changes to Babel, you will need to transpile your ES6 before Node.js can run it.
So, we'll add our first script, build, in file package.json.
"scripts": {
"build": "babel index.js -d dist"
}
Then we'll add our start script in file package.json.
"scripts": {
"build": "babel index.js -d dist", // replace index.js with your filename
"start": "npm run build && node dist/index.js"
}
Now let's start our server.
npm start
I Tried with all the methods, but nothing worked.
I got one reference from GitHub.
To use TypeScript imports with Node.js, I installed the below packages.
1. npm i typescript --save-dev
2. npm i ts-node --save-dev
Won't require type: module in package.json
For example,
{
"name": "my-app",
"version": "0.0.1",
"description": "",
"scripts": {
},
"dependencies": {
"knex": "^0.16.3",
"pg": "^7.9.0",
"ts-node": "^8.1.0",
"typescript": "^3.3.4000"
}
}
Step 1
yarn add esm
or
npm i esm --save
Step 2
package.json
"scripts": {
"start": "node -r esm src/index.js",
}
Step 3
nodemon --exec npm start
Node v14.16.0
For those who've tried .mjs and got:
Aviator#AW:/mnt/c/Users/Adrian/Desktop/Programming/nodejs_ex$ node just_js.mjs
file:///mnt/c/Users/Adrian/Desktop/Programming/nodejs_ex/just_js.mjs:3
import fetch from "node-fetch";
^^^^^
SyntaxError: Unexpected identifier
and who've tried import fetch from "node-fetch";
and who've tried const fetch = require('node-fetch');
Aviator#AW:/mnt/c/Users/Adrian/Desktop/Programming/nodejs_ex$ node just_js.js
(node:4899) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/mnt/c/Users/Adrian/Desktop/Programming/nodejs_ex/just_js.js:3
import fetch from "node-fetch";
^^^^^^
SyntaxError: Cannot use import statement outside a module
and who've tried "type": "module" to package.json, yet continue seeing the error,
{
"name": "test",
"version": "1.0.0",
"description": "to get fetch working",
"main": "just_js.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT"
}
I was able to switch to axios without a problem.
import axios from 'axios'; <-- put at top of file.
Example:
axios.get('https://www.w3schools.com/xml/note.xml').then(resp => {
console.log(resp.data);
});
I found the 2020 update to the answer in this link helpful to answering this question as well as telling you WHY it does this:
Using Node.js require vs. ES6 import/export
Here's an excerpt:
"Update 2020
Since Node v12, support for ES modules is enabled by default, but it's still experimental at the time of writing this. Files including node modules must either end in .mjs or the nearest package.json file must contain "type": "module". The Node documentation has a ton more information, also about interop between CommonJS and ES modules."
I'm new to Node.js, and I got the same issue for the AWS Lambda function (using Node.js) while fixing it.
I found some of the differences between CommonJS and ES6 JavaScript:
ES6:
Add "type":"module" in the package.json file
Use "import" to use from lib.
Example: import jwt_decode from jwt-decode
Lambda handler method code should be define like this
"exports.handler = async (event) => { }"
CommonJS:
Don't add "type":"module" in the package.json file
Use "require" to use from lib.
Example: const jwt_decode = require("jwt-decode");
The lambda handler method code should be defines like this:
"export const handler = async (event) => { }"
In my case. I think the problem is in the standard node executable. node target.ts
I replaced it with nodemon and surprisingly it worked!
The way using the standard executable (runner):
node target.ts
The way using the nodemon executable (runner):
nodemon target.ts
Do not forget to install nodemon with npm install nodemon ;P
Note: this works amazing for development. But, for runtime, you may execute node with the compiled js file!
To use import, do one of the following.
Rename the .js file to .mjs
In package.json file, add {type:module}
If you are using ES6 JavaScript imports:
install cross-env
in package.json change "test": "jest" to "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
more in package.json, add these:
...,
"jest": {
"transform": {}
},
"type": "module"
Explanation:
cross-env allows to change environment variables without changing the npm command. Next, in file package.json you change your npm command to enable experimental ES6 support for Jest, and configure Jest to do it.
This error also comes when you run the command
node filename.ts
and not
node filename.js
Simply put, with the node command we will have to run the JavaScript file (filename.js) and not the TypeScript file unless we are using a package like ts-node.
If you want to use BABEL, I have a simple solution for that!
Remember this is for nodejs example: like an expressJS server!
If you are going to use react or another framework, look in the babel documentation!
First, install (do not install unnecessary things that will only trash your project!)
npm install --save-dev #babel/core #babel/node
Just 2 WAO
then config your babel file in your repo!
file name:
babel.config.json
{
"presets": ["#babel/preset-env"]
}
if you don't want to use the babel file, use:
Run in your console, and script.js is your entry point!
npx babel-node --presets #babel/preset-env -- script.js
the full information is here; https://babeljs.io/docs/en/babel-node
I had this error in my NX workspace after upgrading manually. The following change in each jest.config.js fixed it:
transform: {
'^.+\\.(ts|js|html)$': 'jest-preset-angular',
},
to
transform: {
'^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular',
},
I had this issue when I was running migration
Its es5 vs es6 issue
Here is how I solved it
I run
npm install #babel/register
and add
require("#babel/register")
at the top of my .sequelizerc file my
and go ahead to run my sequelize migrate.
This is applicable to other things apart from sequelize
babel does the transpiling
Just add --presets '#babel/preset-env'.
For example,
babel-node --trace-deprecation --presets '#babel/preset-env' ./yourscript.js
Or
in babel.config.js
module.exports = {
presets: ['#babel/preset-env'],
};
To make your import work and avoid other issues, like modules not working in Node.js, just note that:
With ES6 modules you can not yet import directories. Your import should look like this:
import fs from './../node_modules/file-system/file-system.js'
For people coming to this thread due to this error in Netlify functions even after adding "type": "module" in package.json file, update your netlify.toml to use 'esbuild'. Since esbuild supports ES6, it would work.
[functions]
node_bundler = "esbuild"
Reference:
https://docs.netlify.com/functions/build-with-javascript/#automated-dependency-bundling
The documentation is confusing. I use Node.js to perform some local task in my computer.
Let's suppose my old script was test.js. Within it, if I want to use
import something from "./mylocalECMAmodule";
it will throw an error like this:
(node:16012) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
SyntaxError: Cannot use import statement outside a module
...
This is not a module error, but a Node.js error. Forbid loading anything outside a 'module'.
To fix this, just rename your old script test.js into test.mjs.
That's all.
My solution was to include babel-node path while running nodemon as follows:
nodemon node_modules/.bin/babel-node index.js
You can add in your package.json script as:
debug: nodemon node_modules/.bin/babel-node index.js
NOTE: My entry file is index.js. Replace it with your entry file (many have app.js/server.js).
I had the same problem when I started to use Babel... But later, I
had a solution... I haven't had the problem any more so far...
Currently, Node.js v12.14.1, "#babel/node": "^7.8.4", I use babel-node and nodemon to execute (Node.js is fine as well..)
package.json: "start": "nodemon --exec babel-node server.js "debug": "babel-node debug server.js"!! Note: server.js is my entry
file, and you can use yours.
launch.json. When you debug, you also need to configure your launch.json file "runtimeExecutable":
"${workspaceRoot}/node_modules/.bin/babel-node"!! Note: plus
runtimeExecutable into the configuration.
Of course, with babel-node, you also normally need and edit another file, such as the babel.config.js/.babelrc file
In case you're running nodemon for the Node.js version 12, use this command.
server.js is the "main" inside package.json file, replace it with the relevant file inside your package.json file:
nodemon --experimental-modules server.js
I recently had the issue. The fix which worked for me was to add this to file babel.config.json in the plugins section:
["#babel/plugin-transform-modules-commonjs", {
"allowTopLevelThis": true,
"loose": true,
"lazy": true
}],
I had some imported module with // and the error "cannot use import outside a module".
If you are using node, you should refer to this document. Just setup babel in your node app it will work and It worked for me.
npm install --save-dev #babel/cli #babel/core #babel/preset-env
When I used sequelize migrations with npx sequelize db:migrate, I got this error, so my solution for this was adding the line require('#babel/register'); into the .sequelizerc file as the following image shows:
Be aware you must install Babel and Babel register.
Wrong MIME-Type for JavaScript Module Files
The common source of the problem is the MIME-type for "Module" type JavaScript files is not recognized as a "module" type by the server, the client, or the ECMAScript engine that process or deliver these files.
The problem is the developers of Module JavaScript files incorrectly associated Modules with a new ".mjs" (.js) extension, but then assigned it a MIME-type server type of "text/javascript". This means both .js and .mjs types are the same. In fact the new type for .js JavaScript files has also changed to "application/javascript", further confusing the issue. So Module JavaScript files are not being recognized by any of these systems, regardless of Node.js or Babel file processing systems in development.
The main problem is this new "module" subtype of JavaScript is yet known to most servers or clients (modern HTML5 browsers). In other words, they have no way to know what a Module file type truly is apart from a JavaScript type!
So, you get the response you posted, where the JavaScript engine is saying it needs to know if the file is a Module type of JavaScript file.
The only solution, for server or client, is to change your server or browser to deliver a new Mime-type that trigger ES6 support of Module files, which have an .mjs extension. Right now, the only way to do that is to either create a HTTP content-type on the server of "module" for any file with a .mjs extension and change your file extension on module JavaScript files to ".mjs", or have an HTML script tag with type="module" added to any external <script> element you use that downloads your external .js JavaScript module file.
Once you fool the browser or JavaScript engines into accepting the new Module file type, they will start doing their scripting circus tricks in the JS engines or Node.js systems you use.

vue cli build with target lib: "require is not defined" when component is imported

I'm trying to export a Vue component as a package, and using vue cli to build the dist. I intend to publish it on npm, but I'm currently using a symbolic link for testing purpose. However even with a simple hello-world project I can't make a valid package.
I created a project:
vue create hello-world
Then I modified the package.json:
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build --target lib --name vue-hello-world ./src/components/HelloWorld.vue",
"lint": "vue-cli-service lint"
},
"main": "./dist/vue-hello-world.common.js",
Then I call
npm run build
and it compiles without error.
Then I make an import in a vue component in another project (I used a symbolic link in node_modules):
import HelloWorld from "hello-world";
On page render I get the following error:
[Vue warn]: Failed to resolve async component: function MediaViewerPdf() {
return Promise.all(/*! import() */[__webpack_require__.e(62), __webpack_require__.e(46)]).then(__webpack_require__.bind(null, /*! ./viewers/MediaViewerPdf.vue */ "./vuejs/components/mediaViewer/viewers/MediaViewerPdf.vue"));
}
Reason: ReferenceError: require is not defined
Any idea what's happening?
Remarks:
using vue inspect, I checked that in webpack config that:
target: "web"
I already set resolve.symlinks at false on the importing project.
EDIT: I have confirmed that it doesn't come from the symbolic link, I have exactly the same error with package directly on node_modules.
Repo with whole code: https://github.com/louis-sanna/vue-hello-world
So I asked the question on the vue-cli repo and I got the solution! https://github.com/vuejs/vue-cli/issues/4245
Turns out NODE_ENV was already set at development in my shell, so it was the mode used to make the build.
Just need to set the mode explicitly and it works:
vue-cli-service build --target lib --name vue-hello-world ./src/components/HelloWorld.vue --mode production
You may need to add it to vue.config.js:
config
.mode("production")
This happens due to the fact that Vue CLI Webpack setup by default does not import commonjs modules, as described in your "main" field in package.json. So the problem is with the project that attempts import, not with the project that exports the component.
There are two ways to attempt to solve this problem.
From the importing project side
You can remedy this by installing babel plugins for the project that imports your components and setting babel.config.js
module.exports = {
presets: [
'#vue/app'
],
plugins: [
'#babel/plugin-transform-modules-commonjs', // leave to import .common.js files
'#babel/plugin-transform-modules-umd' // leave to import .umd.js files
]
}
But doing this alone will not be sufficient: you also will need to import CSS that is generated with the library by adding this in your entry file
import 'hello-world/dist/vue-hello-world.css';
Note that I have only tested this using yarn link, but I have confidence that this will work with an imported separate npm module just fine.
From the library side
The intent (I suppose) of the original question - how do I bundle a library so my users don't have to do this little dance each time they want to use it?
Option 1: don't bundle it - provide .vue files and sources. Just include everything in 'src' directory of your module, write a readme with explanation and be done with it. Let the importing project figure the compilation and bundling out.
Option 2: use rollup with Vue plugin to roll components into bundle. There is an example on how to do that. In that example you can see that your project will be able to import .esm build
https://github.com/vuejs/rollup-plugin-vue/tree/master/cookbook/library
Not sure how you are creating the symbolic link, but you should use npm link for that. If you are still having problems (like I did myself) I would suggest you try npm-link-better:
npm install -g npm-link-better
cd vue-hello-world
npm link
cd ../hello-world
nlc -w vue-hello-world
For building component libraries, I suggest you have a look at vue-cli-plugin-component. This plugin already sets up the vue-cli project pretty well.

CRA and bundle-loader

I am trying to use react-router with code splitting inside my create-react-app application.
import loadSettings from 'bundle-loader?lazy!./Settings';
This line gets my an error:
Line 5: Unexpected '!' in 'bundle-loader?lazy!./Settings'. Do not use import syntax to configure webpack loaders import/no-webpack-loader-syntax
I assume this is because of some es-lint settings. How can I disable it so I can use webpack bundle-loader inside my CRA application?
I somehow managed to solve this.
What I did is:
Eject the creact-react-app by running npm run eject
Modify the package.json file by adding a rules key to the eslintConfig so it looks like this:
"eslintConfig": {
"extends": "react-app", // This was already in the file
"rules": {
"import/no-webpack-loader-syntax": 0
}
}
Set your components like described in the docs.
Hope this helps someone, as I have digged through many forums without finding the right answer!
BTW support for code splitting with dynamic import should be coming to CRA soon!

Turn off ESLint rule (in React app, using WebStorm)

I am writing a React app in WebStorm using the standard React setup. I have never previously explicitly set up any linting, so whatever error/warning messages are showing up are from some sort of default configuration. When I run npm start I get the following warning:
Compiled with warnings.
Warning in ./path/to/MyComponent.js
/my/complete/path/to/MyComponent.js
19:49 warning Unexpected whitespace before property bind no-whitespace-before-property
...
You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.
The last two lines make it explicitly clear that the warnings are from ESLint (as opposed to, say, JSHint or some custom React linting, etc.).
I want to keep ESLint running, i.e. I don't just want to globally disable all linting. However, I want to turn the "no-whitespace-before-property" warning off everywhere, not just on one line or in one file. How do I do that?
My package.json shows the following for npm start (which is what I run when the warnings appear):
"scripts": {
"start": "react-scripts start",
...
}
I am developing in WebStorm. The ESLint preferences panel has the "Enable" checkbox unchecked, so all of the ESLint configuration options in the IDE are grayed-out and presumably irrelevant, so presumably also the configuration and invocation of ESLint are happening elsewhere (e.g. built into React?).
I tried putting the following .eslintrc.json file into my project home directory:
{
"rules": {
"no-whitespace-before-property": "off"
}
}
alone as well as with "extends": "eslint:recommended".
I tried adding the following to my project's package.json file:
{
...
"eslintConfig": {
"rules": {
"no-whitespace-before-property": "off"
}
}
}
I've also tried setting the value to 0 instead of to "off".
It may or may not be relevant that I'm writing a React app, and it may or may not be relevant that I'm developing in WebStorm, but I include those facts just in case.
I've checked around on StackOverflow and can't find an answer.
The note below the errors is not coming from ESLint (error is). So I'm assuming you are using some sort of wrapper, like github.com/facebookincubator/create-react-app Those wrappers do not use .eslintrc file and can't be configured directly. You will have to read through documentation of your wrapper to figure out how to disable this rule.
In general ESLint wrappers like create-react-app, standard, xo, etc. are specifically designed to "just work", and hence remove ability to configure and fine tune styles/rules.

Categories

Resources