Im using gatsby-plugin-root-import package in Gatbsy for using absolute imports. Absolute imports work but Eslint throws an error "import/no-unresolved".
I tried to use this code:
module.exports = {
...
"settings": {
"import/resolver": {
"node": {
"paths": ["src"]
}
},
},
But it doesn't work. Is there any solution for this problem?
gatsby-plugin-root-import config:
{
resolve: "gatsby-plugin-root-import",
options: {
src: path.join(__dirname, "src"),
pages: path.join(__dirname, "src/pages"),
component: path.join(__dirname, "src/component"),
images: path.join(__dirname, "src/assets/images"),
fonts: path.join(__dirname, "src/assets/fonts"),
styles: path.join(__dirname, "src/styles"),
}
}
You can install the eslint-import-resolver-alias plugin as dev dependency like
npm install -D eslint-import-resolver-alias
and then edit your eslint config to specify the alias
module.exports = {
...
"settings": {
"import/resolver": {
"alias": {
"map": [
["src", "./src"],
["pages", "./src/pages"],
["component", "./src/component"],
["images", "./src/images"],
["fonts", "./src/fonts"],
["styles", "./src/styles"],
],
"extensions": [".js", ".jsx"]
}
},
},
Basically you need to provide all the alias as maps to eslint too
Related
I add typescript config for paths:
{
//.....
"moduleResolution": "node",
{
"baseUrl": "app",
"paths": {
"#app/*": ["*"],
"#folder/*": ["folder/*"],
//Other paths
},
}
Added configuration to webpack:
resolve: {
extensions: [".tsx", ".ts", ".js", ".jsx", ".css", ".json"],
alias: {
"#app":path.resolve(__dirname + "../", "app"),
"#services":path.resolve(__dirname + "../app", "folder")
},
modules: [
"node_modules", path.resolve(process.cwd(), "app")
],
plugins: [
new TsConfigPathsPlugin({
configFile: "../tsconfig.json"
}),
],
},
And here is my .eslint file:
"settings": {
"import/resolver": {
"node": {
"paths": [
"app"
],
"extensions": [
".ts",
".tsx",
".jest.tsx",
".d.ts"
]
}
}
After that I try import somthing like this:
import {component} from "#folder/component";
Everything is assembled, the compiler generates no errors
But I get error in eslint:
ESLint: Unable to resolve path to module '#folder/component'.(import/no-unresolved)
I've been trying to figure this out for the third day
The customer does not want to install additional plugins
I would be very grateful for your help!
the node resolver doesn't understand TypeScript paths. So it's specifically looking for a node module called #folder/component - which won't exist.
You can use the typescript resolver for the plugin:
https://www.npmjs.com/package/eslint-import-resolver-typescript
I'm building a project from scratch on React + TypeScript and using the Webpack Dev server.
I want to use relative paths to components, which will be not strict for a more flexible development.
In my App.tsx, I'm trying to import component:
import EntityTypes from "components/EntityTypes/EntityTypes";
and getting an error
Module not found: Error: Can't resolve 'components/EntityTypes/EntityTypes' in '/home/eugene/prj/work/crud-react/src'
File by this path exists (/src/components/EntityTypes/EntityTypes.js) and exports the class like
export default EntityTypes;
My tsconfig.json:
{
"compilerOptions": {
"sourceMap": true,
"noImplicitAny": false,
"module": "commonjs",
"target": "es5",
"lib": [
"es2015",
"es2017",
"dom"
],
"removeComments": true,
"allowSyntheticDefaultImports": false,
"jsx": "react",
"allowJs": true,
"baseUrl": ".",
"paths": {
"components/*": [
"src/components/*"
]
}
}
}
webpack.config.js:
const HtmlWebPackPlugin = require( 'html-webpack-plugin' );
const path = require( 'path' );
module.exports = {
context: __dirname,
entry: './src/index.js',
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
output: {
path: path.resolve( __dirname, 'dist' ),
filename: 'main.js',
publicPath: '/',
},
devServer: {
historyApiFallback: true
},
module: {
rules: [
{
test: /\.(tsx|ts)?$/,
loader: 'awesome-typescript-loader'
},
{
test: /\.js$/,
use: 'babel-loader',
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|j?g|svg|gif)?$/,
use: 'file-loader'
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: path.resolve( __dirname, 'public/index.html' ),
filename: 'index.html'
})
]
};
I've checked the documentation of typescript about "paths", the file is exists, I don't understand what the problem.
I have sorted out how to use paths for my files and make them flexible, that I can reorganize the project and manage paths easy without a lot of changes of strict relative paths.
The problem was related to configuration of the webpack.
Final configuration is next:
tsconfig.json
{
"compilerOptions": {
// ...
"paths": {
"~/components/*": [
"./src/components/*"
],
"~/services/*": [
"./src/services/*"
],
"~/interfaces/*": [
"./src/interfaces/*"
]
},
}
}
webpack.config.js
const path = require('path');
module.exports = {
// ...
resolve: {
// ...
alias: {
'~/components': path.resolve(process.cwd(), './src/components'),
'~/interfaces': path.resolve(process.cwd(), './src/interfaces'),
'~/services': path.resolve(process.cwd(), './src/services'),
}
},
}
Examples of usage
import {IEntities} from "~/interfaces/entities.interface";
// ...
import EntityForm from "~/components/EntityForm/EntityForm";
Just add tsconfig-paths-webpack-plugin into your webpack configuration:
const { cwd } = require('node:process');
const { resolve } = require('node:path');
const TsconfigPathsWebpackPlugin = require('tsconfig-paths-webpack-plugin');
module.exports = {
resolve: {
plugins: [
new TsconfigPathsWebpackPlugin({
configFile: resolve(cwd(), './tsconfig.json'),
})
]
}
};
And you don't need to duplicate paths configuration as webpack aliases.
You're using absolute imports, not relative ones. Try import EntityTypes from "./components/EntityTypes/EntityTypes";, assuming the file you're importing it into is on the same level as the components directory.
I am creating a modular component library with React and TypeScript with Babel 7.
I want the user of my library to import the components by a syntax similar to this:
import SomeComponent from "my-awesome-lib/SomeComponent"
SomeComponent is a TSX module in my-awesome-lib package:
import * as React from "react";
export default function () {
return <h1>SomeComponent</h1>
}
And main field of the package.json file of my-awesome-component is:
"main": "src/index.ts"
I do not want to publish compiled version of my component library, because I am importing CSS and other assets in my components and I expect all the users of my package to use Webpack with some specific configs.
Now my problem is that `import SomeComponent from "my-awesome-lib/SomeComponent" fails with a parse error:
ERROR in ../node_modules/wtf/index.tsx 4:9
Module parse failed: Unexpected token (4:9)
You may need an appropriate loader to handle this file type.
|
| export default function () {
> return <h1>WTF</h1>
| }
It seems Webpack does not load or transform the TSX files in node_modules.
I use this tsconifg.json at the root of my user app (which imports my-awesome-lib):
{
"compilerOptions": {
"outDir": "./dist",
"module": "commonjs",
"target": "es5",
"jsx": "react",
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"esModuleInterop": true,
"downlevelIteration": true,
"lib": ["es5", "es2015", "dom", "scripthost"],
"typeRoots": ["node_modules/#types", "src/#types"],
},
"include": ["src/**/*", "node_modules/**/*"],
"exclude": []
}
And the relevant configurations of Webpack are:
const tsModules = {
test: /\.(js|jsx|ts|tsx)$/,
include: [path.resolve('src')],
exclude: /node_modules/,
loader: 'babel-loader'
}
const resolve = {
alias: {
},
modules: [
'node_modules'
],
extensions: ['.tsx', '.ts', '.js']
}
module.exports = {
...
context: resolve('src'),
resolve: resolve,
module: {
rules: [
tsModules,
...
]
}
}
How can I make Webpack to load and transform TSX modules of my-awesome-lib from node_modules?
This setup assuming you are using styled-components and have no css/scss.
What's important here is that you have "module": commonJS in your tsconfig and libraryTarget: "commonJS" in your webpack config. Externals tells webpack not bundle you're library with React, or React-DOM or styled-components and instead to look for those packages within the project you're importing into.
you're also going to need to take React, react-dom and styled-components out of your package.json dependencies and put those package in your peer-dependencies
const path = require("path");
const fs = require("fs");
const TerserPlugin = require('terser-webpack-plugin');
const appIndex = path.join(__dirname, "../src/main.tsx");
const appBuild = path.join(__dirname, "../storybook-static");
const { TsConfigPathsPlugin } = require('awesome-typescript-loader');
module.exports = {
context: fs.realpathSync(process.cwd()),
mode: "production",
bail: true,
devtool: false,
entry: appIndex,
output: {
path: appBuild,
filename: "dist/Components.bundle.js",
publicPath: "/",
libraryTarget: "commonjs"
},
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
},
'react-dom': {
root: 'ReactDOM',
commonjs2: 'react-dom',
commonjs: 'react-dom',
amd: 'react-dom'
},
"styled-components": {
root: "styled-components",
commonjs2: "styled-components",
commonjs: "styled-components",
amd: "styled-components"
}
},
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
parse: {
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
comparisons: false,
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
ascii_only: true,
},
},
parallel: true,
cache: true,
sourceMap: false,
})
],
},
resolve: {
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx", ".ts", ".tsx"],
alias: {
"react-native": "react-native-web",
},
},
module: {
strictExportPresence: true,
rules: [
{ parser: { requireEnsure: false } },
{
test: /\.(ts|tsx)$/,
loader: require.resolve("tslint-loader"),
enforce: "pre",
},
{
oneOf: [
{
test: /\.(tsx?)$/,
loader: require.resolve('awesome-typescript-loader'),
options: {
configFileName: 'tsconfig.prod.json'
}
},
],
},
],
},
plugins: [
new TsConfigPathsPlugin()
],
node: {
dgram: "empty",
fs: "empty",
net: "empty",
tls: "empty",
child_process: "empty",
},
performance: false,
};
note: it's important that you target a point in you're application as an entry that ONLY has the components you want to export.
I.E For me it's Main.tsx and inside Main.tsx it looks like this.
export { Checkbox } from "./components/Checkbox/Checkbox";
export { ColorUtils } from "./utils/color/color";
export { DataTable } from "./components/DataTable/DataTable";
export { DatePicker } from "./components/DateTimePicker/DatePicker/DatePicker";
export { DateTimePicker } from "./components/DateTimePicker/DateTimePicker/DateTimePicker";
export { Disclosure } from "./components/Disclosure/Disclosure";
This means webpack won't bundle things you're not meaning to export. To test you're bundle works try importing something with require syntax from the bundle to get around typescript typings and turn allowJS true in tsconfig.
something like
const Button = require("../path/to/js/bundle").Button
console.log(Button);
I found create-react-library extremely helpful
You are excluding your node_modules directory (which generally is a good thing):
const tsModules = {
test: /\.(js|jsx|ts|tsx)$/,
include: [path.resolve('src')],
exclude: /node_modules/,
loader: 'babel-loader'
}
Besides explicitely excluding the node_modules folder, you also only allow the content of the src folder to be processed by babel-loader because of your include property in tsModules. So this error:
ERROR in ../node_modules/wtf/index.tsx 4:9 Module parse failed:
Unexpected token (4:9)
makes sense.
You can still exclude node_modules except for a single folder if you remove the tsModules.include property and change your regular expression in tsModules.exclude:
const tsModules = {
// ...
exclude: /node_modules\/(?!my-awesome-lib)\/*/
// ...
}
Or you could, but I haven't tested it yet, add the my-awesome-lib dir to the include array:
const tsModules = {
// ...
include: [
path.resolve(__dirname, './src'),
path.resolve(__dirname, './node-modules/my-awesome-lib')
]
// ...
}
Then files in your node_modules/my-awesome-lib directory will pass the babel-loader which will transform the typescript code.
Edit: I think you confusion is coming from your tsconfig.json file with "include": ["src/**/*", "node_modules/**/*"],. Babel is transpiling your code, not typescript. So having a tsconfig.json file in your root directory may help your IDE (especially if you are using Microsoft's VScode), but has no effect on how babel and #babel/preset-typescript transform your code.
I have to host a js file on a server to be imported into any html page.
We have written some react components for the same purpose.
When we import the un-minified js file in the html, it works fine.
But, when we use the minified js file, it doesn't work. That means, it doesn't show anything in the browser.
We are using webpack for bundling the react components. yarn build
Babel-loaders to transpile the jsx code to js
I have tried to manually transpile the jsx code and then minify it. In this case the minified file also works.
But, it doesn't work when I transpile it through the my project config.
The difference between the manually minified and the projects minified file was that the manually minified file has the reference of the js files where React components are written.
.babelrc
{
"presets": [
["latest"],
"es2015",
"flow",
"react",
"stage-2",
],
"plugins": [
"syntax-dynamic-import",
],
"env": {
"production": {
"plugins": [
"transform-react-remove-prop-types",
"transform-react-inline-elements"
]
},
"development": {
"plugins": [
"transform-react-jsx-source"
]
},
"test": {
"presets": [
["latest"],
"es2015",
"flow",
"react",
"stage-2",
],
"plugins": [
"syntax-dynamic-import",
"transform-react-jsx-source"
]
}
}
}
webpack.config.js
const path = require('path');
const paths = require('./webpack.paths.js');
const loaders = require('./webpack.loaders.js');
const plugins = require('./webpack.plugins.js');
module.exports = {
entry: [path.resolve(paths.embed, 'index.js')],
output: {
path: paths.productionRoot,
filename: 'filename.js',
},
resolve: {
extensions: ['.js', '.jsx'],
alias: Object.assign({}, {
'react': 'preact-compat',
'react-dom': 'preact-compat',
}),
},
module: {
loaders: [
loaders.eslint,
loaders.iFrameJs,
loaders.css,
],
},
plugins: [
plugins.environmentVariables,
],
};
I guess the problem with .babelrc file configuration.
Would you please give a try using #babel/preset-react as recommended on babeljs site? https://babeljs.io/docs/en/babel-preset-react
Example :
npm install --save-dev #babel/preset-react
.babelrc file (Usage)
{ "presets": ["#babel/preset-react"] }
I changed the webpack config and removed the below piece of code.
alias: Object.assign({}, {
'react': 'preact-compat',
'react-dom': 'preact-compat',
}),
The react and preact version mismatch was causing the problem.
New webpack config
module.exports = {
entry: [path.resolve(paths.embed, 'index.js')],
output: {
path: paths.productionRoot,
filename: 'termly.js',
},
resolve: {
extensions: ['.js'],
},
module: {
loaders: [
loaders.eslint,
loaders.js,
loaders.css,
],
},
plugins: [
plugins.environmentVariables,
],
};
This solved the issue
I am trying to use async and await in my react application.
onSubmit = async (model) => {
await this.setState({ data: model });
}
After adding the above code i get an error in my browser console.
ReferenceError: regeneratorRuntime is not defined
.babelrc
{
"presets": ["#babel/preset-env", "#babel/preset-react"],
"plugins": [
"#babel/plugin-proposal-class-properties"
],
"sourceMaps": "inline"
}
webpack.config.js
const path = require("path");
const WebpackShellPlugin = require("webpack-shell-plugin");
const nodeExternals = require("webpack-node-externals");
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = [
{
Server config removed
},
{
entry: {
app1: './src/public/app1/index.js',
app2: './src/public/app2/index.js',
app3: './src/public/app3/index.js',
},
devtool: "source-map",
output: {
path: __dirname + '/dist/public/',
publicPath: '/',
filename: '[name]/bundle.js',
devtoolLineToLine: true,
sourceMapFilename: "[name]/bundle.js.map",
},
module: {
rules: [
{
test: /(\.css|.scss)$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
},
{
test: /\.(jsx|js)?$/,
use: [{
loader: "babel-loader",
// options: {
// cacheDirectory: true,
// presets: ['react', 'es2015'] // Transpiles JSX and ES6
// }
}]
}
],
},
"plugins": [
new CopyWebpackPlugin([
{
from: 'src/public/app1/index.html',
to: 'app1'
},
{
from: 'src/public/app2/index.html',
to: 'app2'
},
{
from: 'src/public/app3/index.html',
to: 'app3'
},
]),
]
}
];
I have added my babelrc and webpack config. Please let me know if i am missing something that would cause this error to appear in my browser console.
Import regeneratorRuntime in the component using async/await:
import regeneratorRuntime from "regenerator-runtime";
*** UPDATED ANSWER *** (probably don't use above)
Import babel and #babel/plugin-transform-runtime plugin:
package.json
"devDependencies": {
"#babel/core": "^7.8.7",
"#babel/plugin-transform-runtime": "^7.8.3",
},
.babelrc
{
"plugins": ["#babel/plugin-transform-runtime"]
}
You did not include your package.json file, so it is a bit unclear what you are missing.
Assuming you have #babel/polyfill as a dependency in your package.json file, is it possible that you are not specifying:
import '#babel/polyfill'
in your React file (such as index.js)?
Adding polyfills from create-react-app worked for me.
yarn add --dev react-app-polyfill
Then add the following lines to webpack.config.js
entry: {
app: [
'react-app-polyfill/ie9', // Only if you want to support IE 9
'react-app-polyfill/stable',
'./src/index.jsx',
],
},
See more examples on the react-app-polyfill GitHub page.