What does the # symbol do in javascript imports? - javascript

For example:
import Component from '#/components/component'
In the code I'm looking at it behaves like ../ going up one level in the directory relative to the file path, but I'd like to know more generally what it does. Unfortunately I can't find any documentation online due to the symbol searching problem.

The meaning and structure of the module identifier depends on the module loader or module bundler. The module loader is not part of the ECMAScript spec. From a JavaScript language perspective, the module identifier is completely opaque. So it really depends on which module loader/bundler you are using.
You most likely have something like babel-plugin-root-import in your webpack/babel config.
Basically it means from the root of the project.. it avoids having to write things like import Component from '../../../../components/component'
Edit: One reason it exists is because import Component from 'components/component' doesn't do that but instead search in the node_modules folder

Know it's old, but I wasn't exactly sure how it's defined, so looked it up, came by, dug a little deeper and finally found this in my Vue-CLI (Vue.js) generated Webpack config
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'#': path.join(__dirname, '..', dir)
}
},
so it's an alias which in this case points to the root of vue-cli generated src directory of the project
Update: As correctly mentioned by #aderchox in the comments, this is a general Webpack feature and not limited to Vue

To make Ben's answer more comprehensive:
First you need to add babel-plugin-root-import in your devDependencies in package.json (If using yarn: yarn add babel-plugin-root-import --dev).
Then in your .babelrc add the following lines into plugins key:
"plugins": [
[
"babel-plugin-root-import",
{
"rootPathPrefix": "#"
}
]
]
Now, you can use #. For example:
Instead of
import xx from '../../utils/somefile'
You Can
import xx from '#/utils/somefile'

As said above, this feature is not in JS by default. You have to use a babel plugin to enjoy it. And its job is simple. It allows you to specify a default root source for your JS files and helps you map your file imports to it.
To get started install through either npm:
npm install babel-plugin-root-import --save-dev
or
yarn add babel-plugin-root-import --dev
Create a .babelrc in the root of your app and configure these settings to your taste:
{
"plugins": [
["babel-plugin-root-import", {
"rootPathSuffix": "the-preferred/root/of-all-your/js/files",
"rootPathPrefix": "#"
}]
]
}
With the config above, you can simply import from that source like:
import Myfile from "#/Myfile"
without doing all this funky stuff:
"/../../../Myfile"
Note that you can also change the symbol to anything like "~" if that floats your boat.

I am using VS code to build react native Apps.
What you need is:
create a jsconfig.json under root path of your App
in your jsconfig.json, add the following code:
{
"compilerOptions": {
"baseUrl": ".",
"target": "ES6",
"module": "commonjs",
"paths": {
"#/*": ["src/*"],
"#components/*": ["src/components/*"],
"#core/*": ["src/core/*"]
}
},
"exclude": ["node_modules"]
}
basically like "shortcut" : ["abs_path"]

In case you are using Typescript, you could achieve this by simply using your tsconfig.json like this:
{
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"#lib/*": ["app/lib/*"]
}
},
}

// # is an alias to /src
Inspired by Can Rau's answer I made a similar discovery in my src/views/Home.vue file. This file was created with the latest (July 2021, Ubuntu 20.04) versions: npx #vue/cli create myfirstvue --default.
I "inferred" it was /src but wanted to know why, because Ben's accepted answer said it would be the root of my project, which in fact is the parent, of /src.
Here is Home.vue:
...
<script>
// # is an alias to /src
import HelloWorld from '#/components/HelloWorld.vue'
</script>
It is defined by Vue Webpack template, which I learned from this other SO answer.

It is a way of remapping module paths, not part of the ES itself, you have to use babel import feature.

Related

How to customize the initial path to the route of the folder in react?

When I am doing import of different files I have to be very careful on the folder nesting where do I call the imports.
I know that it is possible to set a generic variable path to import files directly pointing at the route of my SRC folder, but I never done it and I am just unable to find the information on the web about it on how to configure it (every search come around react-router which is not what I need). Could someone explain me how to make it happen:
import dataJSON from "../../data/data.json";
import IconPath from "../../assets/svg/icons.svg";
become something approximate like
import dataJSON from "{myRoute}/data/data.json";
import IconPath from "{myRoute}/assets/svg/icons.svg";
so that I don't have to worry all the time to think about nest depth when I code and organise my components in folders.
Thank you!
For Javascript :
Create a jsconfig.json file in the root of your project with the following content:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
For Typescript:
You already have tsconfig.json file in the root of project. Just need to add baseurl setting in compile options key.
{
...//other ts config
"compilerOptions": {
..., // other complie options
"baseUrl": "src"
},
...//other ts config
}
Here baseUrl is what we're adding into compileoptions.
after adding this file and configuration you can import files as following.
Before:
import Component1 from '../../../../Components/Component1'
After:
import Component1 from 'Components/Component1'
Anything you import will be absolute imports from src folder.
Hope this is what you're looking for.
Alternatively, you can let your IDE do the work for you (importing and moving files around). The gif below is WebStorm, I believe MS Code does it too.
You can use babel-plugin-module-resolver.
This plugin can simplify the require/import paths in your project. For example, instead of using complex relative paths like import dataJSON from "../../data/data.json";, you can write import dataJSON from "data/data.json";. It will allow you to work faster since you won't need to calculate how many levels of the directory you have to go up before accessing the file.
Install the plugin
npm install --save-dev babel-plugin-module-resolver
or
yarn add --dev babel-plugin-module-resolver
Create a jsconfig.json file and use the code.
{
"compilerOptions": {
"baseUrl": "src"
},
"include": [
"src"
]
}
That's it.

How to configure module aliases in a monorepo bootstrapped with Turborepo?

I am attempting to migrate several repositories to the monorepo architecture and I am currently working on a POC bootstrapped with Turborepo.
The issue I am seeing is that ts module aliasing isn't configured properly. I currently have a single ui package and I am trying to export a button component from the index.tsx like so (notice, VS code not complaining, it thinks it can resolve the module):
However, when I attempt to build my application I see that the module is not in fact resolved:
Module not found: Can't resolve '#/components/Button'
I am at a loss here, does anyone know how to properly configure module aliases with turbo repo? Below is the tsconfig.json:
{
"extends": "tsconfig/react-library.json",
"include": ["."],
"exclude": ["dist", "build", "node_modules"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/components/*": ["./components/*"]
}
}
}
Look on this thread. You will have to do a little bit of trial and error to get this right. But this answer will get us in the right direction.

Confusing behavior when wiring together Rollup, ES modules, TypeScript, and JSX

The things I noted in the title - I started to learn them just recently. They are going not that smooth, so I have to ask this little question on StackOverflow.
What I require
Something to pack my stuff - here comes Rollup
Bare module imports for my own module files - using #rollup/plugin-node-resolve for this
Funny typed language - TypeScript and #rollup/plugin-typescript
React with JSX - it is react and react-dom packages, and typescript, which is able to process JSX
I read these docs to wire these tools together:
https://www.typescriptlang.org/tsconfig
https://www.npmjs.com/package/#rollup/plugin-typescript
I successfully used Rollup, #rollup/plugin-node-resolve, and TypeScript. But with addition of React things went odd.
Demo project
Please look at the example project I made for illustration:
https://github.com/Ser5/RollupWireBug
git clone https://github.com/Ser5/RollupWireBug.git
cd RollupWireBug/
npm install or yarn install
npm run build
The project structure is:
/
src/
js/ - only folder that contains my code
main.tsx - entry point
test-class.js - for testing bare import
buggy.tsx - should be excluded from building
dist/
bundle.js - Rollup output file
rollup.config.js
To my understanding the config should work like that:
resolve({
moduleDirectories: ['node_modules/', 'src/js/'],
extensions: ['.js', '.ts', '.jsx', '.tsx'],
}),
^ This should mean to bare import modules from node_modules/ and src/js/, searching for files with noted extensions.
And here comes the puzzling part:
typescript({
include: [
'./**/*',
//'src/js/**/*',
//"node_modules/**/*",
],
exclude: [
"node_modules/",
"dist/",
"src/buggy.tsx",
],
}),
^ This is how a configuration works for me. I must write ./**/* in the include - which seems odd for me, as I believe I don't need to include every file from the project root - I need only src/js/.
If instead of ./**/* I use src/js/**/*, or src/js/**/* with node_modules/**/* - Rollup refuses to build the project, screeching:
src/js/main.tsx → dist/bundle.js...
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src\js\main.tsx (7:13)
5:
6: let myName = 'Ser5';
7: let s = <h1>{myName}</h1>;
^
8: console.log(s);
Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
It doesn't recognize the JSX syntax.
Because of ./**/* in the include I also need to have the exclude section - otherwise Rollup/TypeScript will crawl into src/buggy.js and even dist/, and try to build them as well.
tsconfig.json
I understand it as follows:
"baseUrl": "./",
"paths": {
"*": [
"node_modules/*",
"src/js/*",
],
},
^ "Go search modules in node_modules/ and src/js/ directories."
"outDir": "tsout",
^ Really no idea WTF is this. Looks like some temporary folder.
And if instead of this part in rollup.config.js
typescript({
include: [
'./**/*',
],
...
}),
I write the same thing in tsconfig.json
{
include: [
'./**/*',
],
"compilerOptions": {
...
The project still doesn't build - displaying Error: Unexpected token for JSX syntax.
Questions
Where am I wrong?
Why for #rollup/plugin-typescript I have to include ./**/* right from the root, and block some files with include section? Why can't I simply write src/js/**/* ?
Why include works only for #rollup/plugin-typescript? And I can't write that include in tsconfig.json?
Will try to give you some hints:
outDir option says where the JavaScript files will be generated
#rollup/plugin-typescript will load any compilerOptions from the tsconfig.json file by default. So if you are passing any option to that (like you did in your repo) it will override those ones that you set in tsconfig.json. Might be better to decide where to config stuff for TS
Specifically for your error. See docs here.
You have to do this basically:
import jsx from 'acorn-jsx';
import typescript from '#rollup/plugin-typescript';
export default {
// … other options …
acornInjectPlugins: [jsx()],
plugins: [typescript({ jsx: 'preserve' })]
};
Check Vite out by the way if you want to avoid all this config shenanigans! :)

How to add import shortcuts - alias

I've created a brand new react app
create-react-app demo
I need to create alias for some directories/components like:
import { Header } from '#uicomponents'
Where #uicomponents is shortcut for the path 'src/hello/this/is/the/path/to/ui/components '
All online tutorials telling that I can use alias imports using resolve.alias, but I'm wondering how to do this with brand-new react app?
Theres is no .babelrc or webpack.config.js files.
Any help please?
If you haven't ejected your application from CRA, then you can alias your source directory with using NODE_PATH in your .env file. NODE_PATH=/src/hello/this/is/the/path/to/ui/components.
If you alias without ejecting, it won't allow you to do the #uicomponents or have multiple aliases. Here's an issue on GitHub that talks about it and the relevant CRA page on environment variables.
If you have ejected you can set the alias in the Webpack configuration files and be able to import like you want:
...
resolve: {
alias: {
'#uicomponents': '/src/hello/this/is/the/path/to/ui/components'
}
},
...
UPDATED:
I recommend you to use Craco.
It allows you to customize webpack / babel / any other tool that used in react-scripts internally.
Webpack and Jest aliases is not an exception.
And recently I created a plugin called craco-alias specially for these purposes.
Links: GitHub, npm.
This plugin generates webpack and jest aliases for you automatically.
You just need to install Craco, write a small config for it, then create (or edit) your jsconfig.json / tsconfig.json (it works with TS as well) and specify aliases source in craco-alias config object.
It's easy - you can find all examples on README page.
Of course it works with every command (npm start, npm test, run build build) and allows to pass any CLI arguments.
But, the only problem is that plugin only supports path aliasing, and it doesn't work with module aliases properly.
I hope it will help somebody :)
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 with craco in package.json and configure next:
// craco.config.js
const {CracoAliasPlugin} = require('react-app-alias')
module.exports = {
plugins: [
{
plugin: CracoAliasPlugin,
options: {}
}
]
}
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",
// ...
}

People ask for the # character in import form '#' in nodejs or vuejs [duplicate]

For example:
import Component from '#/components/component'
In the code I'm looking at it behaves like ../ going up one level in the directory relative to the file path, but I'd like to know more generally what it does. Unfortunately I can't find any documentation online due to the symbol searching problem.
The meaning and structure of the module identifier depends on the module loader or module bundler. The module loader is not part of the ECMAScript spec. From a JavaScript language perspective, the module identifier is completely opaque. So it really depends on which module loader/bundler you are using.
You most likely have something like babel-plugin-root-import in your webpack/babel config.
Basically it means from the root of the project.. it avoids having to write things like import Component from '../../../../components/component'
Edit: One reason it exists is because import Component from 'components/component' doesn't do that but instead search in the node_modules folder
Know it's old, but I wasn't exactly sure how it's defined, so looked it up, came by, dug a little deeper and finally found this in my Vue-CLI (Vue.js) generated Webpack config
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'#': path.join(__dirname, '..', dir)
}
},
so it's an alias which in this case points to the root of vue-cli generated src directory of the project
Update: As correctly mentioned by #aderchox in the comments, this is a general Webpack feature and not limited to Vue
To make Ben's answer more comprehensive:
First you need to add babel-plugin-root-import in your devDependencies in package.json (If using yarn: yarn add babel-plugin-root-import --dev).
Then in your .babelrc add the following lines into plugins key:
"plugins": [
[
"babel-plugin-root-import",
{
"rootPathPrefix": "#"
}
]
]
Now, you can use #. For example:
Instead of
import xx from '../../utils/somefile'
You Can
import xx from '#/utils/somefile'
As said above, this feature is not in JS by default. You have to use a babel plugin to enjoy it. And its job is simple. It allows you to specify a default root source for your JS files and helps you map your file imports to it.
To get started install through either npm:
npm install babel-plugin-root-import --save-dev
or
yarn add babel-plugin-root-import --dev
Create a .babelrc in the root of your app and configure these settings to your taste:
{
"plugins": [
["babel-plugin-root-import", {
"rootPathSuffix": "the-preferred/root/of-all-your/js/files",
"rootPathPrefix": "#"
}]
]
}
With the config above, you can simply import from that source like:
import Myfile from "#/Myfile"
without doing all this funky stuff:
"/../../../Myfile"
Note that you can also change the symbol to anything like "~" if that floats your boat.
I am using VS code to build react native Apps.
What you need is:
create a jsconfig.json under root path of your App
in your jsconfig.json, add the following code:
{
"compilerOptions": {
"baseUrl": ".",
"target": "ES6",
"module": "commonjs",
"paths": {
"#/*": ["src/*"],
"#components/*": ["src/components/*"],
"#core/*": ["src/core/*"]
}
},
"exclude": ["node_modules"]
}
basically like "shortcut" : ["abs_path"]
In case you are using Typescript, you could achieve this by simply using your tsconfig.json like this:
{
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"#lib/*": ["app/lib/*"]
}
},
}
// # is an alias to /src
Inspired by Can Rau's answer I made a similar discovery in my src/views/Home.vue file. This file was created with the latest (July 2021, Ubuntu 20.04) versions: npx #vue/cli create myfirstvue --default.
I "inferred" it was /src but wanted to know why, because Ben's accepted answer said it would be the root of my project, which in fact is the parent, of /src.
Here is Home.vue:
...
<script>
// # is an alias to /src
import HelloWorld from '#/components/HelloWorld.vue'
</script>
It is defined by Vue Webpack template, which I learned from this other SO answer.
It is a way of remapping module paths, not part of the ES itself, you have to use babel import feature.

Categories

Resources