How can i use #import to import my components in my scripts from other folders in my react project.
For example i have a folder structure like this
src
|
--- App.jsx
|
--- pages
| |___ home.jsx
|
|
--- components
|__ HomeComponent.jsx
How can i use in home.jsx
import HomeComponent from "#components/HomeComponent"
if i just try to use import HomeComponent from "#components/HomeComponent" like
this i get error module not found.
You can do a relative import from pages/home.jsx like this
import HomeComponent from "../components/HomeComponent"
Here ../ means you are going up one directory level and then into components directory
You can also perform absolute imports by setting up additional tools like babel or webpack. An absolute import would look like this when you have set src as your root directory
import HomeComponent from "components/HomeComponent"
If you are using create-react-app, this setup is easy to do as all the tooling is already handled by create-react-app
You can read about it here under the absolute imports section - https://create-react-app.dev/docs/importing-a-component/
babel-plugin-module-resolver
This plugin can simplify the require/import paths in your project. For example, instead of using complex relative paths like ../../../../utils/my-utils, you can write #utils/my-utils. It will allow you to work faster since you won't need to calculate how many levels of directory you have to go up before accessing the file.
// Use this:
import MyUtilFn from 'utils/MyUtilFn';
// Instead of that:
import MyUtilFn from '../../../../utils/MyUtilFn';
// And it also work with require calls
// Use this:
const MyUtilFn = require('utils/MyUtilFn');
// Instead of that:
const MyUtilFn = require('../../../../utils/MyUtilFn');
Install the plugin
npm install --save-dev babel-plugin-module-resolver
or
yarn add --dev babel-plugin-module-resolver
Specify the plugin in your .babelrc with the custom root or alias. Here's an example:
{
"plugins": [
["module-resolver", {
"root": ["./src"],
"alias": {
"test": "./test",
"underscore": "lodash"
}
}]
]
}
.babelrc.js version
Specify the plugin in your .babelrc.js file with the custom root or alias. Here's an example:
const plugins = [
[
require.resolve('babel-plugin-module-resolver'),
{
root: ["./src/"],
alias: {
"test": "./test"
}
}
]
];
Good example: https://gist.github.com/nodkz/41e189ff22325a27fe6a5ca81df2cb91
Related
I have a parent repository developed with React, and I have a child Sub Module inside of it(which is developed by react too):
The project folder structure is something like below:
parent
/.git
/nodemodule
/src
/subModules/childProject
/.git
/src
/js
/x.jsx // i want this file from parent project
/...
/...
I want to access and use the x.jsx component from parent project. I imported it like blow in my parent project:
import X from '../subModules/childProject/src/js/x.jsx'
but it gives me unexpected token!
7 | return (
> 8 | <article className="center">
| ^
9 | this is test global component with in child Project
10 | </article>
11 | )
it looks like that it cannot transform it because I wrote just a test function in old JavaScript way like:
export default function test(x) {
return x * 2
}
It imported without any error and works but when I wrote function in arrow style like below:
export default function test(x) => x * 2
it does not work. It seems like it's just a runtime error of transpiling modules, how can I transpile and import react components from child submodule in to parent repository?
The problem was that Babel does not know that there is a submodule project in the root of the project, just by changing my .babelrc file to babel.config.js and configuring it by babelrcRoots I would be able to solve the issue:
Now my babel.config.js file looks like this:
module.exports = {
"presets": [
"#babel/preset-react",
"#babel/preset-env"
],
"plugins": [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-proposal-object-rest-spread"
],
"babelrcRoots": [ "./", "./subModules/someFolder" ]
}
Now I can import any react component and JS modules from sub-repository in side my parent project and it works correctly.
I created an NPM package that uses Webpack and Babel for transpiling/bundling.
In my package.json, I've got main set to "main": "build/index.js". And in my Webpack config, I have entry set to entry: { app: './src/index.js' }. My entry file is shown below.
Everything works fine when the package is installed. However, with this setup, two import paths are exposed for every helper:
This is a problem for editors that support auto imports, since they will sometimes auto import from 'my-package/build/utils/helper1' rather than the preferred path of 'my-package'.
So, two questions:
Is there any way to prevent the longer import path from being exposed?
What is considered best practice when creating NPM packages. Is my setup acceptable, or should I be doing something different?
Entry File:
import helper1 from './utils/helper1';
import helper2 from './utils/helper2';
export {
helper1,
helper2,
};
const myPackage = {
helper1,
helper2,
};
export default myPackage;
you can utilize Webpack resolve
I often use the first way:
export {
helper1,
helper2,
};
Recently, I found that we can use Object.freeze() to export. This is a good article.
I would suggest probably merge your helper1 and helper2 in one file and name it helpers, then you can put them in the class myPackage so that you then export them as a module like this
import myPackage from './utils/helper';
// OR import {helper1, helper2} from './utils/helpers';
export default class myPackage {
helper1,
helper2,
};
OR
import {myPackage} from './utils/helpers';
// OR import {helper1, helper2} from './utils/helpers';
module.exports.myPackage = (helper1, helper2) => {
this.helper1 = helper1;
this.helper2 = helper2;
};
I hope this helps.
I am kinda new in the web and would like to ask a simple question.
Basically I just want to eliminate dots from my import. I mean thing like:
import Component from '../../container/etc'
How could I just start my import from the root? So its would become smth like:
import Component from 'container/etc'
I used create-react-app for set up
You can add the resolve config in webpack like
module.exports = {
//things here
resolve: {
extensions: ['.jsx', '.scss', '.js', '.json'],
modules: [
path.resolve(__dirname, 'app'),
'node_modules'
]
}
// other things here
}
where you directory structure would be like
-- app
-- container
-- etc.js
-- api.json
so you can import like
import ETC from 'container/etc';
import json from 'api.json'
In case you are using create-react-app, you can create a .env file on the root of your project and make the NODE_PATH point to the src folder (or wherever you have your code) all you'll have to do is write:
NODE_PATH=src
Create-react-app will read your .env file without ejecting.
We would like to create bundle.js from React and webpack, where a per build configuration is included and made available to the React code, but we are not sure how to go about doing this.
The idea would be to be to do something like:
npm run build -- config="config123.json"
And then have the generated bundle.js include that configuration, such that it could be used by the root container. Something like:
import React from 'react';
import ReactDOM from 'react-dom';
import RootContainer from './containers/main-container';
ReactDOM.render(
<RootContainer config={configPassedByBuildProcess}/>,
document.getElementById('app')
);
Is this possible and if so, how should we approach this?
No, I don't believe that you can pass a file on build, from what I know the only thing that you can pass is a string like an ENV variable. You could import the config123.json file like this
import React from 'react';
import ReactDOM from 'react-dom';
import RootContainer from './containers/main-container';
import config from '/path/to/config123.json'
ReactDOM.render(
<RootContainer config={config}/>,
document.getElementById('app')
);
You may need a JSON loader for importing JSON files
After a bit of experimenting, the solution I have found is to use Webpack's DefinePlugin, since this provides a way of doing string substitution during webpack's build phase.
In my React code I defined:
// Will be substituted by webpack's DefinePlugin. Not an error.
const bundleConfig = BUNDLE_CONFIG;
and then in my webpack.config.js I first load my config (hard coded for now):
// The path can be pulled in via 'process.args' and parsed as appropriate
const bundleConfig = fs.readFileSync('bundle-config/default-config.json', 'UTF-8');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'BUNDLE_CONFIG': bundleConfig
})
]
}
Note that if for some reason we want to build with a missing or undefined bundleConfig, then the right substitution would likely be the string (not the keyword) 'undefined' , to keep the code valid, such that:
const bundleConfig = 'undefined';
module.exports = {
plugins: [
new webpack.DefinePlugin({
'BUNDLE_CONFIG': bundleConfig
})
]
}
Just one extra thing was the configuration of the package.json (scripts section only):
{
"scripts": {
"build": "run() { NODE_ENV=production && webpack -p $1; }; run",
}
}
This allow passing in the path to the webpack.conf.js script, when we call:
npm run build /path/to/config.json
I get the file structure like this
before build
I want to make it like this below with webpack
after build
BTW, I also want to use ES6 import and export for the module loader,
such as in nav.js
class Nav extends Component {
// react code here
}
export defalt Nav
and in header.js
import Nav from `nav/bundle`
// header react code
// .......
export defalt Header
also need the bundle the redux and react-route npm package within the node_module
is it possible for webpack to do this stuff? some suggestions?
Here's a rough idea you could try to adapt:
{
// generate these dynamically through JavaScript
entry: {
footer: <path to footer js>,
...
},
output: {
path: './demo',
filename: '[name]/bundle.js' // name maps to entry keys
},
...
}