I have an index.ts file with multiple exports in my react + typescript project. I am using that file to import things from. I have more than one index.ts in my project and this sometimes causes circular dependencies in my project especially when writing tests using jest.
My question is that what will happen when I import one or more things from index.ts files? Does webpack use this file to find paths and load only the requested module using the path or all exported things are loaded in the function? ( do A and B load into C or only A will be loaded into C by webpack in the below example?)
here is one simple pattern of such a circular dependency:
// -- index.ts --
export {default as A} from './A'
export {default as B} from './B'
export {default as C} from './C'
// -- A.tsx --
import { B, C } from './index'
export class A{
/* as is */
}
// -- B.tsx --
import { A} from './index'
export class B extends A {
/* as is */
}
// -- C.tsx --
import { A} from './index'
export class C extends A {
/* as is */
}
accoriding to this, I assume that there is a central repository for webpack that all theses imports are cached there and whenever an import occures, it will check there first and if no match found, it will try to find the module. In this case, my assumption that all index.ts exports are loaded is wrong.
I am looking for help to answer my ambiguity about all these behaviors of webpack, nodeJs, typescript or anything that is responsible for this
Webpack only loads the specific modules that are imported in your code and not the entire file.
In the example you provided, when you import B and C from index.ts in A.tsx, webpack will only load the B and C modules and not the entire index.ts file. Similarly, when you import A from index.ts in B.tsx and C.tsx, only the A module will be loaded.
As for your question about circular dependencies, webpack can handle circular dependencies, but it can lead to unexpected behavior. It's best to avoid them whenever possible in order to have a maintainable codebase.
Related
I'm trying to use code splitting in my react app and overall it works great, but I noticed something strange in bundle analyzer. My components folder is loaded in the first chunk with all its components (even the ones that are only used in lazy loaded components).
I think the problem is that I follow the structure of using index.ts files to export my components:
/components:
/Component1
/Child1
Child1.tsx
index.ts
Component1.tsx
index.ts
/Component2
Component2.tsx
index.ts
index.ts
The index.ts files just export the needed components like so
export * from './Component';
this is the same as
import { Component } from './Component';
export { Component };
in javascript.
By doing it that way I get very nice looking imports:
import { Component } from 'components';
without the deep paths and all that stuff.
But i think because of that webpack can not recognize how to split it and just bundles it all.
Are there any solutions for this? Maybe I'm doing something wrong?
I use the default create react app config right now.
export * from './Component';
This is causing webpack to bundle all the components which are there in './Component' and whatever it importing and so on.
You should export components individually without using *
Like export { Component1, Component2 } from './Component'
Also if you are using Webpack 5, it creates a mapping of which component import is used and discard unused components. This is not available in Webpack 4.
I am trying to publish a package on npm. I'm not sure how to phrase what I am trying to do..maybe packaging "sub modules"?
The abbreviated directory structure is:
- package.json
- src/
- a.js
- b.js
- dist/
- a.js
- b.js
My build script uses Babel to transpile to the dist directory with the same modules as in src/. I would like
consumers to import functions from the a.js module like so:
import {foo} from "mypackage/a";
not
import {foo} from "mypackage/dist/a";
If I add an index.js to mypackage/ and export a I can do
import {a} from "mypackage"
but that's not what I want...
What is the standard way to publish packages so "sub modules" can be imported like this or can someone point me to a repo that does this kind of thing?
If I understand, there should be two options that you can choose.
First, let me try to explain how Node sub-modules with a slash are handled by Node.
When you import the module with a slash, Node will try to look in the root folder for a file with the name that is specified after the slash. In your case, it will be a.js. In case nothing is found, Node will try to look for the directory named a containing the file index.js. If no file is found, nothing is imported.
So back to your problem, you can either create file a.js in your root folder containing the following export:
export * from './dist/a';
// The traditional export should look like this, in case I have wrong ES6 export
module.exports = require('./dist/a')
or change the structure of your project a bit, so files a and b are located in their specific directories.
For example:
- package.json
- src/
- a.js
- b.js
- a/
- index.js
- b/
- index.js
I have a react app set up with webpack, and would like to also have a script that runs in node to write stuff into output file, such as:
script.mjs
import fs from 'fs';
import {SomeClass} from './index.js';
const outputFile= fs.createWriteStream(__dirname + '/output.png');
// Writes into output file
and have the following script command in package.json:
"scripts": {
...
"runFile": "node --experimental-modules test/script.mjs",
...
}
Whenever I run npm run runFile it complains with:
import {SomeClass} from './index.js';
^^^^^^^^^
SyntaxError: The requested module './index.js' does not provide an export named 'SomeClass'
even though it exists in that file:
./index.js
export SomeClass from './SomeClass';
I even used node -r esm test/script.js to run in node, but it keeps complaining about ES6 exports all the time. Could anybody point me to how to run a js file that has ES6 stuff with node command?
NODE v10
There is a small inconsistency in your export/import statements.
Oh, and you are exporting from an entirely different file. Is there are reason you need to do so?
You may export an containing your class
export { someClass
Then you can import it with the present import statement.
More direct would be to export from your ./someClass file with a default export
export default someClass
then import it without destructuring the object:
import some class from './someClass';
The latter would fit well with the file name and is a style expected by most.
Note that when you run old node versions you need some extra CLI flags to run modules. With present node (^13) it is enough to set type: module. See Hao Wu's answer.
I have a large amount of javascript files in src/, I don't want to manually go in and require all my files.
|- /src
|- a.js
|- b.js
|- c.js
|- more.js
| - index.js
index.js
import a from 'a.js'
import a from 'b.js'
import a from 'c.js'
//import more
export default {
a,
b,
c,
// more
}
Is there a way to do this with rollup or a plugin that someone has written to do this?
English is not my native language; please excuse typing errors.
When you export a module it is automatically imported, so you can do:
export * from 'a.js';
export * from 'b.js';
// ...
If you don't need to import those modules later, but just include them in the bundle, you can import them like this:
import 'a.js';
import 'b.js';
And so on.
You can also take a look at https://www.npmjs.com/package/rollup-plugin-glob-import.
I am looking to create a main import file using ES6 syntax. I have a components directory with an index.js file.
I would like to export the imports if that makes sense. Essentially, I would like to import then export the individual component files into the index file so I can de-structure my imports from any other files like so:
import {Comp1, Comp2} from "./components"
How do I do this with ES6 syntax?
You can do:
export * from "./components"
// or
export {Comp1, Comp2} from "./components"
How exactly to reference components/index.js depends on your module loader or the module format you're compiling to. I'm not sure what happens if you do export * from multiple modules that have overlapping named exports (will have to check).