Lazy-loaded modules warnings after updating Angular from 8 to 9 - javascript

After Angular update all lazy-loaded modules return warning:
Error: [path/to/module/module-name.ts] is missing from the TypeScript
compilation. Please make sure it is in your tsconfig via the 'files'
or 'include' property.
My function which returns modules array:
export function manifests(prefix = '') {
return [
{
loadChildren: () => import(prefix + '/path/to/a.module').then(m => m.AModule),
path: 'a',
},
{
loadChildren: () => import(prefix + '/path/to/b.module').then(m => m.BModule),
path: 'b',
},
]
}
If I replace that function with static array everything seems to be fine, though. Why?
My tsconfig.app.json:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
"src/polyfills.ts",
"src/zone-flags.ts",
],
"include": [
"src/**/*.d.ts",
]
}

In my case, for some reason, the file name in the import statements were capatilized.
For instance, let's say I had the following .ts file: companySearchModel.ts
export class CompanySearchModel {
//some properties
}
The import statement in another file, where the companySearchModel is used, looked like this:
import { CompanySearchModel } from './models/CompanySearchModel.ts'
When it should have looked, like this:
import { CompanySearchModel } from './models/companySearchModel.ts'
Not sure why this happened, but hopefully this will help you.

you can add this path to exclude in tsconfig below include property
"exclude": [
"path/to/module"
]

Related

Error vue/typescript Cannot find module and it's path error can't find module or its corresponding type declarations

Hi, I'm having this erreor while doing the Router view:
Cannot find module '#/src/views/HomeView.vue' or its corresponding type declarations.
I had tried different paths and had changed the tsconfig.vue file, but still get the error.
// tsconfig.json
{
"extends": "#vue/tsconfig/tsconfig.web.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/*": ["./*"]
}
},
"references": [
{
"path": "./tsconfig.config.json"
}
]
}
// router/index.ts
import HomeView from '#/src/views/HomeView.vue'
import HomeView from '#/views/HomeView.vue'
const routes = {
'/': HomeView,
}

Vue 3 on Vite.js with Eslint — Unable to resolve path to module eslint(import/no-unresolved)

I use Vue 3 on Vite.js with Eslint + Airbnb config. Airbnb config has a rule eslint(import/no-unresolved), which is good, but Eslint doesn't know how to resolve alias path.
I want to use aliases for paths — example:
import TableComponent from '#/components/table/TableComponent.vue'˙
Environment is in plain JavaScript.
I managed to set up my vite.config.js so that the app can resolve paths like this:
import path from 'path';
import { defineConfig } from 'vite';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: [{
find: "#", replacement: path.resolve(__dirname, 'src')
},],
},
});
Vue app works like that and resolves the import path correctly, but Eslint keeps reporting the error: Unable to resolve path to module eslint(import/no-unresolved)
How and where can I tell Eslint how to resolve aliases?
I have tried:
install eslint-plugin-import eslint-import-resolver-alias --save-dev
// .eslintrc.js
// ...
extends: [
'eslint:recommended',
'plugin:import/recommended',
'airbnb-base',
'plugin:vue/vue3-strongly-recommended',
],
settings: {
'import/resolver': {
alias: {
map: [
['#', 'src'],
],
},
},
},
But that doesn't work.
EDIT:
Solved the issue, see the accepted answer if you're using plain JavaScript like I do.
If you're using TypeScript, see if Seyd's answer can help you.
this solves the issue in my TypeScript project.
npm install eslint-import-resolver-typescript
After eslint-import-resolver-typescript installation
{
// other configuration are omitted for brevity
settings: {
"import/resolver": {
typescript: {} // this loads <rootdir>/tsconfig.json to eslint
},
},
}
should be added to .eslintrc.js.
my tsconfig.json (remove unwanted settings)
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": false,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"types": ["vite/client", "node"],
"baseUrl": ".",
"paths": {
"#/*": ["src/*"]
},
"allowJs": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"exclude": ["node_modules"]
}
Check the discussion here:
In case someone runs into this problem, this works in my case*:
settings: {
'import/resolver': {
alias: {
map: [
['#', './src'],
],
},
},
},
*In my case, Vue's root is 'src' directory, while Eslint's is one level higher, so it needs the './src' path.
Huge thanks to #https://github.com/aladdin-add for the answer through the github question!
I had the same problem, and even I fixed the src path it still hat the issue. It did not work until I added extensions:
"settings": {
"import/resolver": {
"alias": {
"map": [
["#", "./src"]
],
"extensions": [".js",".jsx"] <--- HERE
}
}
},
1. Use & export aliases in vite.config.js
// vite.config.js
import { resolve } from 'path';
import { defineConfig } from 'vite';
export const aliases = {
'#': resolve(__dirname, './src'),
'#u': resolve(__dirname, './src/utils'),
};
export default () => defineConfig({
// ...
resolve: {
alias: aliases,
},
})
2. Create .eslintrc with ES Modules support. (Thanks to Morgan's answer)
2.1 npm i esm -D
2.2 Create sibling to .eslintrc.js — .eslintrc.esm.js.
2.3 Put your your ESLint config into .eslintrc.esm.js.
// .eslintrc.esm.js
export default {
root: true,
extends: ['#vue/airbnb', 'plugin:vue/recommended'],
// ...
}
2.4 Inside .eslintrc.js include this code:
const _require = require('esm')(module)
module.exports = _require('./.eslintrc.esm.js').default
3. Import, map & use aliases from vite.config.js in .eslintrc.esm.js
3.1 npm i eslint-import-resolver-alias -D
3.2 Inside .eslintrc.esm.js include following code:
// .eslintrc.esm.js
import { aliases } from './vite.config';
const mappedAliases = Object.entries(aliases).map((entry) => entry); // [[alias, path], [alias, path], ...]
export default {
// ...
settings: {
'import/resolver': {
alias: {
map: mappedAliases,
},
},
},
}
I can't for the life of me get this to work, I've tried everything above. Is there something else wrong with my file?
// .eslintrc.cjs
/* eslint-env node */
require("#rushstack/eslint-patch/modern-module-resolution");
module.exports = {
root: true,
extends: [
"airbnb",
"plugin:vue/vue3-essential",
"eslint:recommended",
"#vue/eslint-config-prettier",
],
parserOptions: {
ecmaVersion: "latest",
},
// Using the accepted answer
settings: {
"import/resolver": {
alias: {
map: [["#", "./src"]],
},
},
},
};
** UPDATE **
The only way I was able to get this to work was using this: eslint-config-airbnb link here, the readme was particularly helpful.
npm add --dev #vue/eslint-config-airbnb #rushstack/eslint-patch
My .eslintrc.js is now:
/* eslint-env node */
require("#rushstack/eslint-patch/modern-module-resolution");
const path = require("node:path");
const createAliasSetting = require("#vue/eslint-config-airbnb/createAliasSetting");
module.exports = {
root: true,
extends: [
"plugin:vue/vue3-essential",
"#vue/eslint-config-airbnb", // <-- added
"eslint:recommended",
"#vue/eslint-config-prettier",
],
parserOptions: {
ecmaVersion: "latest",
},
rules: {
"import/no-unresolved": "error",
},
settings: {
...createAliasSetting({
"#": `${path.resolve(__dirname, "./src")}`,
}),
},
};
Huzzah!
In the README.md of eslint-plugin-import it is said:
Currently Node and webpack resolution have been implemented, but the resolvers are just npm packages, so third party packages are supported (and encouraged!).
Here you can see the list of the third party resolvers.
One that worked for me was this: eslint-import-resolver-custom-alias, and this is how I used it:
settings:
import/resolver:
eslint-import-resolver-custom-alias:
alias:
'#': './app/javascript'
extensions:
- '.js'
- '.vue'
For me the # had been set as an alias for app/javascript inside vite.config.ts, you should change this based on your project configurations.
in .eslintrc.js add
settings: {
'import/resolver': {
alias: {
map: [['#', './src/']],
extensions: ['.js', '.vue'],
},
},
},

How to make eslint resolve paths mapped in jsconfig

In my nextjs project I have mapped path in jsconfig.json to make easy absolute imports
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"#/*": ["./*"]
},
"target": "es6",
"module": "commonjs",
"experimentalDecorators": true
}
}
My import paths look like this
import { VIEW } from '#/src/shared/constants';
My eslintrc.js has settings specified as
module.exports = {
... ,
settings: {
"import/resolver": {
alias: {
extensions: [".js"],
map: ["#", "."]
}
}
}
}
I am still getting the error saying can't resolve "#/what/ever/my/path/is"
How do I make eslint realize the jsconfig path
I was using babel-eslint as my parser in eslintrc. While searching, I realized I need to add babel-plugin-module-resolver in babelrc to resolve the modules. In this file we can define our mapped paths which are there in our jsconfig.
Hence adding the following plugin in the babelrc file compiled my code successfully.
[
"module-resolver",
{
"alias": {
"#": "./"
}
}
]
According to the docs for eslint-import-resolver-alias, the map property should be an array of arrays, so try this:
module.exports = {
... ,
settings: {
"import/resolver": {
alias: {
extensions: [".js"],
map: [ ["#", "."] ]
}
}
}
}
Also, double-check that you actually have eslint-import-resolver-alias installed - it's easy to forget!

How to intellisense alias module path in VSCode

I would like VSCode to IntelliSense the module path so I can access it by click.
For example, after configurating jsconfig.json I'm able to access ./src/styled/index by importing its global path.
But I couldn't figure out how to make it work with an alias #styles
// VSCode Intellisene Works
import { mixins, theme } from 'styles';
// VSCode Intellisene Doesn't work
import { mixins, theme } from '#styles';
My current jsconfig.json:
{
"compilerOptions": {
"baseUrl": "./",
"jsx": "react",
"paths": {
"#styles": ["src/styles/index"]
}
}
}
Seems I had to restart VSCode.
Javascript (javascript,javascriptreact file types in VSCode)
An example of jsconfig.json file for reference:
{
"compilerOptions": {
"baseUrl": "./src",
"jsx": "react",
"paths": {
"#styles": ["styles/index"],
"#fonts": ["fonts/index"],
"#components": ["components/index"],
"#atoms": ["components/atoms/index"],
"#molecules": ["components/molecules/index"],
"#organisms": ["components/organisms/index"],
"#templates": ["components/templates/index"],
"#icons": ["components/atoms/Icons/index"],
"#config": ["config/index"],
"#utils": ["utils/index"],
"#hooks": ["hooks/index"],
"#constants": ["constants/index"],
"#queries": ["queries/index"],
"#reducers": ["state/store/reducers"],
"#actions": ["state/store/actions"],
"#slices": ["state/slices/"],
"#storybookHelpers": ["../.storybook/helpers"]
}
}
}
An example of how styles/index looks like:
export * from './colors';
export * from './GlobalStyle.styles';
export * from './mixins.styles';
// Or
export { COLORS } from './colors';
export { default as GlobalStyle } from './GlobalStyle.styles';
export { default as mixins } from './mixins.styles';
Will allow import (with IntelliSense):
import { COLORS, mixins, GlobalStyle } from '#styles';
For a bonus: aliases.js, which is a helper which I use to define aliases in webpack config files, it helps to not repeat yourself, for example when using the same aliases in storybook and for the application itself.
// Remember to update `jsconfig.json`
const aliases = (prefix = `src`) => ({
'#actions': `${prefix}/state/store/actions`,
'#atoms': `${prefix}/components/atoms`,
'#molecules': `${prefix}/components/molecules`,
'#organisms': `${prefix}/components/organisms`,
'#templates': `${prefix}/components/templates`,
'#components': `${prefix}/components`,
'#config': `${prefix}/config`,
'#constants': `${prefix}/constants`,
'#hooks': `${prefix}/hooks`,
'#icons': `${prefix}/components/atoms/Icons`,
'#queries': `${prefix}/queries`,
'#reducers': `${prefix}/state/store/reducers`,
'#slices': `${prefix}/state/slices`,
'#styles': `${prefix}/styles`,
'#utils': `${prefix}/utils`,
'#storybookHelpers': `../.storybook/helpers`,
});
module.exports = aliases;
// usage example at .storybook/webpack.config.js file
const path = require("path");
const alias = require(`../src/config/aliases`);
const SRC = "../src";
const aliases = alias(SRC);
const resolvedAliases = Object.fromEntries(
Object.entries(aliases).map(([key, value]) => [
key,
path.resolve(__dirname, value),
])
);
module.exports = ({ config }) => {
config.resolve.modules.push(path.resolve(__dirname, SRC));
config.resolve.alias = resolvedAliases;
return config;
};
Typescript (typescript,typescriptreact files)
At tsconfig.json use the compilerOptions.paths option, notice that the paths are relative to baseUrl:
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"#components/*": ["components/*"],
"#config": ["config"],
"#constants": ["constants"],
"#hooks": ["hooks"],
"#styles": ["styles"],
"$types/*": ["types/*"],
"#utils": ["utils"]
}
}
This allows aliases (with IntelliSense), for example:
// Example of hooks/index.ts file
export * from './useLogin';
export * from './useLocalStorage';
export * from './useAuth';
// Usage examples
import {ROUTES} from '#constants';
import {Text} from '#components/atoms';
import {mixins} from '#styles';
import {useLocalStorage} from '#hooks';
In the settings.json file, add this line:
"typescript.preferences.importModuleSpecifier": "non-relative"
If this property is removed, then the ugly relative auto-import is the default option. Simply change 'typescript' to 'javascript' if you're currently using JS. To know more about this setting option, just hover on it like this:
(Bonus tip) Prefix #app/ to all import paths with the following compiler options in tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#app/*": ["./*"]
}
},
}
I had the right configuration as described by the other answers. In VS code I restarted the TypeScript server using Ctrl + Shift + P -> TypeScript: Restart TS server command and it fixed the editor highlighting the import path error.
Just for completeness here is what my tsconfig.json looks like:
{
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"#/*": ["./src/*"]
}
},
"include": ["src/**/*"]
}
As a side note, make sure the include in your jsconfig/tsconfig is pointing to correct paths.
For anyone like me who the other answers aren't working for, these are the tsconfig bits that worked for me, in addition to the settings addition in the accepted answer and ensuring you're setting includes/excludes properly:
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/*": ["./src/*"],
}
}
Full credit to this gist: https://gist.github.com/EmilyRosina/eef3aa0d66568754a98382121fefa154

Typescript library to single global javascript file

I'm writing a Typescript library with this structure:
and file contents:
restApi.class.ts
import { restApiOptions } from '../models/rest.options.model';
import { StoreMethods } from '../routes/store.methods.class';
import { UserMethods } from '../routes/user.methods.class';
export class RestApi {
public storeRest: StoreMethods;
public userRest: UserMethods;
constructor(private restApiOptions: restApiOptions) {
.....
}
setLanguage(langId: number){
.....
}
}
store.methodds.class.ts
import { Observable } from 'rxjs';
import { restApiOptions } from '../models/rest.options.model';
import { routeMethods } from '../core/routeMethods.interface';
export class StoreMethods implements routeMethods {
constructor(private restApiOptions: restApiOptions) {
.....
}
setLanguage(languageId: number){
......
}
getStore(storeId: number): Observable<any> {
.....
}
}
and public_api.ts
export { RestApi } from './lib/core/restApi.class'
the library is intended to be used as a dependency in an Angular2+ project, so i have a tsconfig file with the next configuration to transpile it and generate definition files
{
"compilerOptions": {
"outDir": "./dist/",
"declaration": true,
"module": "commonjs",
"target": "es5",
"lib": [
"es2017",
"dom",
"es2015",
"es5",
"es6"
]
},
"exclude": [
"node_modules",
]
}
The problem i have is that this library also needs to be used in a plain es5 javascript project in an "old fashioned way", that is, including the javascript library file in a script tag and using it in a way like this:
var myRestApi = new RestApi(options)
I'm using webpack to combine all files into a single bundle.js file but after generating this file and including it in the project I don't have access to the RespApi class.
this is my webpack.config.js
const path = require('path');
module.exports = [{
entry: './src/public_api.ts',
module: {
rules: [{
test: /\.tsx?$/,
use: [{
loader : 'ts-loader',
options:{
configFile : 'tsconfig.json'
}
}],
exclude: /node_modules/
}]
},
resolve: {
extensions: ['.ts', '.js', '.tsx']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dev')
}
}];
is there a way to transpile the library into a single javascript file and accessing the RestApi class from global??
There's an official guide on webpack's site. I recommend you read it.
Here's the cheatsheet. Add two fields to your webpack.config.js.
webpackConfig.output.library = "RestApi"
webpackConfig.output.libraryTarget = "var"
There's a short coming though. Because you export your module as a named module in public_api.js, user can only access it through window.RestApi.RestApi. Without experimenting, I'm not entirely sure how to solve this.

Categories

Resources