I'm trying to set up an alias in my app built with create-react-app .
I don't use typescript . The IDE (WebStorm) sees my alias paths. Shows the contents of a folder. But when I refresh the page, I get the error:
Module not found: Error: Can't resolve '#HomePage/HomePage' in 'C:\Users\ASUS\WebstormProjects\spnew\client\src'
I'm going to add the HomePage component which is in the HomePage folder.
My way:
1) I made an eject
2) Created a 'jsconfig.json' file in the root directory with react
{
"compilerOptions": {
"baseUrl": ".",
paths: {
"#HomePage/*": ["./src/pages/HomePage/*"]
}
},
"exclude": ["node_modules"]
}
p.s. tried without #, tried to remove './'
p.s.s. after adding this file, the IDE reacts to:
import {...} from "#HomePage/"; tells you what files are in this folder.
3) The auto-generated webpack.config.js file has very few features.
On the Internet they write what needs to be done like this:
modules.exports = {
resolve: {
extensions: ['.js', '.jsx'],
alias: {
Components: path.resolve(__dirname, '../src/components/'),
}
},
...
resolve: {
...
}
}
I already have over 700 lines in this file!
But the structure is the same. I found module.exports which has nested resollve which has nested alias. And added a line with the path.
It looks like this:
alias: {
HomePage: path.resolve(__dirname, "../src/pages/HomePage"),
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
// Allows for better profiling with ReactDevTools
...(isEnvProductionProfile && {
'react-dom$': 'react-dom/profiling',
'scheduler/tracing': 'scheduler/tracing-profiling',
}),
...(modules.webpackAliases || {}),
}
p.s. I tried to write the path './' '../' and without it.
When importing, I get the same error!
Compiled with problems:X
ERROR in ./src/routes.js 9:0-46
Module not found: Error: Can't resolve '#HomePage/HomePage' in 'C:\Users\ASUS\WebstormProjects\spnew\client\src'
Related
I'm struggling to get absolute path to work in a Vite react-ts project.
Here's how I created the project
npm init #vitejs/app
npx: installed 6 in 1.883s
√ Project name: ... test-vite
√ Select a framework: » react
√ Select a variant: » react-ts
Then I added baseUrl to tsconfig.json
based on the TS official doc:
{
"compilerOptions": {
"baseUrl": "./src",
...
followed by adding a simple component (T:\test-vite\src\components\Test.tsx)
import React from "react";
const Test = () => <h1>This is a Test.</h1>;
export default Test;
Finally I import the Test component in App.tsx
but it won't let me use absolute path:
import Test from "components/Test";
I get this error
whereas if I use relative path, the app works in dev & build mode without any error:
import Test from "./components/Test";
How can I make absolute path work in the project?
There are two problems here:
Tell typescript how to resolve import path
Tell vite how to build import path
You only tell typescript how to resolve, but vite don't konw how to build. So refer to the official document resolve.alias, maybe this is what you want:
// vite.config.ts
{
resolve: {
alias: [
{ find: '#', replacement: path.resolve(__dirname, 'src') },
],
},
// ...
}
You can import path like this (or any module under ./src):
import Test from "#/components/Test";
import bar from "#/foo/bar"
Moreover, you can use vite plugin vite-tsconfig-paths directly, it makes you don't have to manually configure resolve.alias
Follow the instructions below:
Install vite-tsconfig-paths as dev dependency
Inject vite-tsconfig-paths using the vite.config.ts module
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
plugins: [tsconfigPaths()],
})
I came here through search results, I was looking for something different, namely, how to do a simple absolute import like import { foo } from 'src/lib/foo.ts'
So if you have a /src directory that contains all code and want to use an absolute import path.
vite.config.ts
export default defineConfig({
...
resolve: {
alias: {
src: path.resolve('src/'),
},
}
})
tsconfig.json
{
"compilerOptions": {
...
"baseUrl": "./"
}
}
Note that this is a trick: src is an alias, so it appears like the path is absolute in Vite. If you have another directory in the root dir, adjacent to /src, you will need to add another alias for that directory.
#Yuns solutions works, but it shows error in vscode. And it was breaking auto-import in vs code.
To make it work in vscode and vite both, I added alias in both tsconfig and vite.config.
// tsconfig.json
{
"paths": {
"#/*": ["src/*"]
}
// ...
}
// vite.config.ts
{
resolve: {
alias: [{ find: '#', replacement: '/src' }],
},
// ...
}
Then, I could import like below (svelte app is in src directory)
import Header from '#/components/Header.svelte
Looking for import {...} from "src/foo/bar";?
I also came here through search results like user Maciej Krawczyk, but the # part also wasn't what I was interested in. That user's answer helped me, but I had trouble with the path.resolve part (ReferenceError because path wasn't defined), so I used a slightly different approach:
vite.config.ts
export default defineConfig({
...
resolve: {
alias: {
src: "/src",
},
},
...
})
Vite's resolver considers the absolute path /src to be from where the server is serving (see GH issue). So if you're running/building from the root of your project with src as a top level directory -- which is pretty common -- this alias points Vite in the right direction.
tsconfig.json
{
"compilerOptions": {
...
"baseUrl": "./",
"paths": {
"src/*": [
"./src/*"
]
}
}
}
This is basically blindly following this StackOverflow answer. TypeScript needs to know that we have special resolving going on as well, otherwise TS will be freaked out about your non-existent src package and not know where it should go looking. (Note: After I changed my TS config, VSCode didn't immediately pick up the change, so I was still getting warnings. I quit, re-opened, and had to wait ~15sec for the warnings to go away.)
1) You need to install these packages:
npm i path
yarn add path
npm i #types/node
yarn add #types/node
npm i vite-tsconfig-paths
yarn add vite-tsconfig-paths
2) Then in the vite.config file:
import { defineConfig } from 'vite';
import react from '#vitejs/plugin-react';
import tsconfigPaths from 'vite-tsconfig-paths';
import path from 'path';
export default defineConfig({
base: './',
resolve: {
alias: {
Components: path.resolve(__dirname, './src/components'),
Assets: path.resolve(__dirname, './src/assets'),
},
},
plugins: [react(), tsconfigPaths()],
});
3) And now we have to tell TS those same paths that we defined in the alias:
{
"compilerOptions": {
...,
"baseUrl": "./",
"paths": {
"src/*": [ "./src/*" ],
// We define this path for all files/folders inside
// components folder:
"Components/*": [ "./src/components/*" ],
// We define this path for the index.ts file inside the
// components folder:
"Components": [ "./src/components" ],
"Assets/*": [ "./src/assets/*" ],
"Assets": [ "./src/assets" ]
}
},
...
}
4) reload vscode: As the comment above said, press Fn1 and type "reload with extensions disabled", re-enabling extensions from the popup.
Now try to import
import Test from "components/Test";
it should work.
For anyone looking specifically to add the nice import "#/something-in-src" syntax like Vue has with the latest (as of posting this answer) version of Vite + React + TypeScript, here's how I did it:
Make sure #types/node is installed as a dev dependency. This didn't come with the latest version of Vite for me, and it will make "path" and __dirname throw an undefined error.
vite.config.ts
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
import path from "path";
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: [{ find: "#", replacement: path.resolve(__dirname, "src") }],
},
plugins: [react()],
});
tsconfig.json
Add:
{
"compilerOptions": {
"paths": {
"#/*": ["./src/*"]
}
}
}
For anyone who stucks after all required changes, you need to reload vscode.
My config files:
tsconfig.json
"baseUrl": "./",
"paths": {
"#/*": ["src/*"]
}
vite.config.ts
import { defineConfig } from 'vite';
import react from '#vitejs/plugin-react';
import path from 'path';
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: { '#': path.resolve(__dirname, './src') },
},
plugins: [react()],
});
In above code you need to have 2 libraries installed:
'path': npm i path
'#types/node': npm i #types/node
After configure your project files you need to reload vscode. To do that press ctrl + P and type ">reload with extensions disabled", after that you will get popUp to activate extensions again click it, and your absoulte path should work
If someone installed vite-tsconfig-paths library, you also need to reload the vscode, remember to import given library to vite.config.ts
export default defineConfig({ plugins: [react(), tsconfigPaths()] });
With package you get default 'components/File' import instead of '#components/File' import.
I would like to use an alias in VUE.JS in a Laravel 5.8 project to import css and js I have in my module.
webpack.mix.js
mix.webpackConfig({
resolve: {
alias: {
'alias': path.resolve(
__dirname,
'~myModule/src'
)
}
}
});
In my VUE App.js I would like import the css folder and I wrote:
resources/js/app.js
// css files
import 'alias/lib/css'
// js files
import 'alias/lib/script'
But I'm wrong something becouse the alias is not resolved:
ERROR in ./resources/js/app.js
Module not found: Error: Can't resolve 'alias/lib/css' in...
Can you help me to fix the issue?
After so many attempts I got the issue. The code was good but I was missing to load the webpack.mix.js properly:
From Laravel Mix documentation:
The webpack.mix.js file is your entry point for all asset compilation. Think of it as a light configuration wrapper around Webpack. Mix tasks can be chained together to define exactly how your assets should be compiled.
But if you are using npm run watch it is not (re)loaded before to compile new changed assets. This means:
if you are in watch mode (npm run watch) exit and restart it to load new updated webpack.config.js if you changed it.
Finally it worked! And it resolve new alias properly!
Here the final config I used in webpack.config.js:
mix.webpackConfig({
resolve: {
alias: {
'aliasName': path.resolve(
__dirname,
'node_modules/MyModule/src/'
)
}
}
});
Another alternative is:
mix.webpackConfig({
resolve: {
modules: [
'node_modules'
],
alias: {
'aliasName' : 'MyModule/src/'
}
}
});
Then in my Vue component (or in vue app.js, just in case)
<template>
<myModule-component></myModule-component>
</template>
require('aliasName/lib/css'); // to load full css directory
require('aliasName/lib/script'); // to load full js directory
import MyModuleComponent from 'aliasName/widgets/MyModuleComponent.vue'
...
export default {
...
components: {
'myModule-component': MyModuleComponent
}
I am currently setting up my project to be a bit cleaner, especially in the frontend part with references.
In hindsight I noticed that I was very generous with the folder structure for my frontend files and ended up with lots of layers. That's why I decided to look into what webpack can do for this case, and found out about the alias functionality.
This is how I set it up:
resolve: {
alias: {
components: path.resolve(__dirname, "Scripts/Views/Components"),
data: path.resolve(__dirname, "Scripts/Data"),
definitions: path.resolve(__dirname, "Scripts/Definitions"),
helper: path.resolve(__dirname, "Scripts/Helper"),
scripts: path.resolve(__dirname, "Scripts"),
views: path.resolve(__dirname, "Scripts/Views"),
},
extensions: [".tsx", ".ts", ".js", ".jsx"],
modules: ["node_modules"]
}
As you can see, I created alias' for various folders here.
This is my folder structure:
Now, let's hop into e.g. the LoginDialog.tsx. Here I am trying to import like this:
import { IErrorAttachedProperty } from "definitions/formHelper";
However, all I end up with here is an error that no module could be found this way.
What am I doing wrong here?
If it is of any significance - The webpack.config.js resides in the same directory as the Scripts folder.
you have to config tsconfig.json for typescript
"baseUrl": "./",
"paths": {
"components/*": [
"./src(or any other path)/Scripts/Views/Components"
]
},
here is nice example ts alias
Ok, so to avoid confusion for others I'm posting my solution/findings:
Yes, you can just use tsconfig.json without needing resolve/alias in Webpack. You should just do it once with Typescript setup.
EDIT: Nope, turns out you do need resolve/alias section in webpack.config.js. Typescript will be happy without it, but then you will get Webpack errors when it builds. Do both to make it work.
TIP: Make sure the paths you provide in the paths section of tsconfig.json are relative to the baseUrl entry point. Don't make them relative to the tsconfig.json file, baseUrl is like the project root for the non-relative module imports defined with paths.
From Typescript docs, absolute modules names (import * from package-a) are relative to baseUrl ~ https://www.typescriptlang.org/docs/handbook/module-resolution.html#base-url
All module imports with non-relative names are assumed to be relative to the baseUrl.
Relative modules (import * from ./packages) are just from current file as stated:
Note that relative module imports are not impacted by setting the baseUrl, as they are always resolved relative to their importing files.
So if you have:
./packages
./package-a
./package-b
./index.ts
./tsconfig.json
Your tsconfig.json would look like:
{
"compilerOptions": {
"baseUrl": "./packages",
"paths": {
"package-a/*": [ "./package-a/*" ],
},
},
"include": [
"./packages/**/*"
]
}
Then your webpack.config.json would look like:
{
resolve: {
alias: {
'package-a': path.resolve(__dirname, 'packages/package-a/'),
}
},
}
Then you can import from index.ts like this:
import { pkgAThing } from 'package-a';
// or
import { otherPkgAThing } from 'package-a/dir/dir`;
Which is alternative to relative style:
import { pkgAThing } from './packages/package-a`;
I make my project by vue-cli.
vue init webpack vue-demo
cd vue-demo
npm install
npm run dev
Now I want to devolop some components. And i want to use them in requirejs.
webpack config
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
filename: '[name].js',
libraryTarget: 'umd',
library:'senyint'
}
Q1:It generate three files. app.js manifest.js vendor.js
The demo has a Hello.vue . I want to require the js file by what webpack generate.
But I require them,it's undefiend . Why? What's the wrong?
Where I should export ?
Now I export in main.js like this.
import Hello from 'components/Hello'
module.exports = {
Hello
}
Q2:I dont want to package without vue.
So i configure this
externals: {
vue: 'vue'
}
If i do this, when npm run dev show error "Uncaught TypeError: Cannot read property 'config' of undefined"
It cause cant find Vue.
If i configure externals vue how to make it run?
Q1:
Open the javascript file app.js i found
define("senyint", ["vue"], factory);
at this line. The 'senyint' is a package name,webpack generate the js,but it doesnt work.
I modify the code like this
define(["vue"], factory);
Require it and it works. But I dont know why.... I just can resolve this problem;
main.js export .vue components
import Hello from 'components/Hello.vue'
export const scom = {
Hello
}
requirejs config
requirejs.config({
baseUrl: 'js/common',
paths: {
module: '../modules'
},
shim: {
app: {
deps:['vue','manifest','vendor']
}
}
})
requirejs(['module/demo', 'app'], function (demojs, app) {
debugger
console.log(app)
})
Q2:
I builded my project with vue-cli webpack template. (not webpack-simple)
In build directory has 'webpack.base.conf.js' and 'webpack.prod.conf.js'
Modify webpack.prod.conf.js add
externals: {
vue: {
root: 'Vue',
commonjs: 'vue',
commonjs2: 'vue',
amd: 'vue'
}
},
and dont add the code in 'webpack.base.conf.js' .Then npm run build it will package without vue.js .Npm run dev use webpack.base.conf.js ,it will run with vue
I am trying to have a namespace for my app to work as a module, and import my components using this namespace and limit the use of relative path.
Although, even though I followed the webpack documentation for alias here: http://webpack.github.io/docs/configuration.html#resolve-alias
I can't make it to work.
This is how my resolve object looks like:
resolve: {
root: path.resolve(__dirname),
alias: {
myApp: './src',
},
extensions: ['', '.js', '.json', '.jsx']
}
path.resolve(__dirname) resolves /Users/Alex/Workspace/MyAppName/ui/
I import my file that way in the file /Users/Alex/Workspace/MyAppName/ui/src/components/Header/index.jsx:
import { myMethod } from 'myApp/utils/myUtils';
I get the following error during the build:
ERROR in ./src/components/Header/index.jsx
Module not found: Error: Cannot resolve module 'myApp/utils/myUtils' in /Users/Alex/Workspace/MyAppName/ui/src/components/Header
# ./src/components/Header/index.jsx 33:19-56
I also tried with modulesDirectories but it doesn't work either.
Do you have any idea what is wrong?
Resolving the alias to the absolute path should do the trick:
resolve: {
alias: {
myApp: path.resolve(__dirname, 'src'),
},
extensions: ['', '.js', '.jsx']
}
Check this webpack resolve alias gist with a simple example.
Another solution to limit the number of relative paths is to add your ./src folder as root instead of aliasing it:
resolve: {
root: [path.resolve('./src')],
extensions: ['', '.js', '.jsx']
}
Then you will be able to require all folders inside ./src as if they where modules. For example, assuming you have the following directory structure:
.
├── node_modules
├── src
│ ├── components
│ └── utils
you would be able to import from components and utils like this:
import Header from 'components/Header';
import { myMethod } from 'utils/myUtils';
Something like having an alias for each folder inside ./src.
This might be obvious to many but if you, like me, have spent too much time trying to figure out why it suddenly does not work when moving from Windows or Mac to Linux then check casing in the paths...
Me and everyone else on the project are using Windows or Mac but at home I dual boot ubuntu which I enjoy using. On cloning our code and running webpack i got a whole lot of Cannot resolve module... errors. I spent more time than I'd like to admit searching for some obscure error in node, npm, webpack or anything until I noticed the paths of the failing modules were something like #app/Shared/settings.js and the require was require('#app/shared/settings'). Windows doesn't care so everything was fine all until I started working on linux. As it turned out problem was not with webpack, node or anything else so that's probably why I didn't find anyone suggesting that this could be the problem.
Hope this saves some time for someone. Or maybe I'm just dumb, I don't know.
Most of the time it depends on your project folder structure. If your webpack file is inside a folder then make sure you handle it accordingly
.
├── node_modules
├── src
│ ├── components
│ └── config/webpack.config.js
modules.exports = {
resolve: {
extensions: ['.js', '.jsx'],
alias: {
Components: path.resolve(__dirname, '../src/components/'),
}
},
...
resolve: {
...
}
}
Also it often happens that we name our folder as "source" but use "src" in path.
Darn! that copy paste has taken alot of my debug time
Hope this helps someone who is facing such issues due to the above reasons.
I got the same error. Finnaly I found the problem was that I wrote resolve twice. And the second resolve override the previous one.
My code is like this:
modules.exports = {
resolve: {
extensions: ['.js', '.jsx'],
alias: {
Components: path.resolve(__dirname, 'src/components/'),
}
},
...
resolve: {
...
}
}
More help can be found in Webpack Doc
I use without next syntax :
resolve: {
alias: {
Data: __dirname + '/src/data'
},
extensions: ['.js', '.jsx', '.json']
}
import points from 'Data/points.json';
In my case, I wanted to alias mobx, so that any import of mobx would always return the same instance, regardless of whether the import call was from my main app, or from within one of the libraries it used.
At first I had this:
webpackConfig.resolve.alias = {
mobx: path.resolve(root, "node_modules", "mobx"),
};
However, this only forced imports of mobx from my app's own code to use the alias.
To have it work for the library's import calls as well, I had to do:
webpackConfig.resolve.alias = {
mobx: path.resolve(root, "node_modules", "mobx"),
"LIBRARY_X/node_modules/mobx": path.resolve(root, "node_modules", "mobx"),
};
It's odd, because I'm pretty sure just having the mobx alias used to work for both contexts before, but now it apparently doesn't (Webpack v4.41.2).
Anyway, the above is how I solved it. (In my case, I needed it to prevent two mobx instances from being used as that breaks things, and LIBRARY_X was symlinked using npm-link, so I couldn't delete/unify the secondary mobx folder itself)