I have the similar folder structure as shown below
/components/organisms
-- ModuleA.vue
-- ModuleB.vue
-- index.js
content of index.js
export { default as ModuleA } from "./ModuleA.vue"
export { default as ModuleB } from "./ModuleB.vue"
If I try to import ModuleB into ModuleA, it generates an error
ModuleA.vue content
<script>
import { ModuleZ } from '#/components/molecules' // component from another directory, it works perfectly
import { ModuleB } from '#/components/organisms' // can't find, error
</script>
You cannot have an cyclic dependency structure with imports.
ModuleA requires index
index requires ModuleA
This generates undefined behaviour when bundled with webpack, usually manifesting as 1 of the files becoming undefined
Related
It's a common thing to create a index.js file in an React application with the only purpose to export several modules, in order to avoid having too many import statements on other components. This can be done by:
index.js
export { Credits } from './Credits.js';
export { SocialMedia } from './SocialMedia.js';
any module that might use those exports:
import * as var_name from index.js
And this is very nice. It wraps exports into a single file. However, when I changed my project to React with typescript, I found that .tsx files cannot be exported like that. The image below is the error I got after changing the project to typescript and the extensions became .tsx
Is there a way of 'bundle' export React .tsx files with the structure shown above? If not, what is the simplest way of centralizing .tsx files export?
My webpack.config.js:
module.exports = {
module: {
rules: [{
test: /\.scss$/,
use: ["sass-loader"]
}]
}
};
You can definitely use the same style of having an index file to group up exports for a whole folder. The simplest way around your problem would be to omit the file extension (assuming you only have one "index" file in the folder).
For example, let's say you have a component in 'common/Example.tsx':
import React from 'react'
export const Example = () => (<div>I'm an example component</div>)
You can then export it in an index file 'common/index.tsx':
export { Example } from './Example'
And import it from somewhere else, e.g. 'App.tsx':
import { Example } from './common'
I currently wanted to optimize handling modules on my application with the implemenation below described. I'm not sure why the page final bundle size increased. It only kept the same bundle size adding on the package.json the flag sideEffects: false
Does Nextjs treeshake modules out-of-the-box?
Module code
// file ModuleA.js
import React from 'react';
const ModuleA = props => (
// some code
);
export default ModuleA;
// file ModuleB.js
import React from 'react';
const ModuleB = props => (
// some code
);
export default ModuleB;
Page code
import ModuleA from '~/ModuleA';
import ModuleB from '~/ModuleB';
// Page size production build 25KB
Optimized module handling
// modules/index.js
export { default as ModuleA } from './ModuleA';
export { default as ModuleB } from './ModuleB';
export { default as ModuleC } from './ModuleC';
export { default as ModuleD } from './ModuleD';
Page code
import {
ModuleA,
ModuleB,
} from '~/modules';
// without sideEffects: false - production build 50KB
// with sideEffects: false - production build 25KB
I have a big project, I try to refactor to ES6 modules right now.
To make further development easier, I wanted to introduce index files, which just export all modules within the directory:
index.js:
export { default as ModuleA } from './moduleA'
export { default as ModuleB } from './moduleB'
export { default as ModuleC } from './moduleC'
moduleA.js:
import { ModuleB } from './index'
moduleB.js:
import { ModuleC } from './index'
ModuleC.doSomething()
moduleC.js:
export default {
doSomething: () => {}
}
Starting point is ModuleA.
The problem is, that in ModuleB ModuleC is undefined, so doSomething can't be executed.
I suspect some issues with circular dependencies, since moduleB tries to access the index again, which parses moduleB before moduleC.
Is it just not possible to do this, or is there another solution?
The issue here is that ModuleC has not been exported by the time that ModuleB is exported and runs, and since ModuleC is a requirement of ModuleB, it can't run. If I were you, I would just export each of them from their own files, and when you import them, import them from their own files instead of index.js.
Example
ModuleA.js:
import { ModuleB } from 'moduleB.js'
export default {
// Your code here
}
ModuleB.js
import { ModuleC } from 'moduleC.js'
moduleC.doSomething();
ModuleC.js
export default {
doSomething: () => {
// Your code
}
}
And finally, since ModuleA is the entry point from index.js, just import it into index.js and run what you need to run.
Alright. Solved it.
The problem ist, that when ModuleB tries to import ModuleC from the index, the index will be parsed again and will see ModuleB before it can reach ModuleC.
It seems to work with only two modules, since the index file doesn't get reparsed, I think.
The solution:
Import modules, which try to load other modules from the index file at last.
So index.js should look like this:
export { default as ModuleA } from './moduleA'
export { default as ModuleC } from './moduleC'
export { default as ModuleB } from './moduleB'
I'm building an npm package (ES6 + Babel) for the first time and I'm having trouble connecting it all together so it can be imported by the end user.
My build (output) folder structure is the same as src:
build
- index.js
- BaseClass.js
sublclasses
- SubClassA.js
- SubClassB.js
SubClassA and SubClassB import and extend BaseClass and are both exported using the module.exports. The entry point, index.js, has only two lines:
import SubClassA from './subclasses/SubClassA'
import SubClassB from './subclasses/SubClassB'
package.json has the main field set to ./build/index.js.
When installing the project (or npm linking) into a test project, I write:
import SubClassA, SubClassB from 'my-package'
Import works, but imported classes are undefined. I've tried a couple more ways to do it, but it didn't work.
How should I do it properly?
EDIT: after changing index.js to:
import SubClassA from './subclasses/SubClassA'
import SubClassB from './subclasses/SubClassB'
module.exports = SubClassA
module.exports = SubClassB
it kind of works. 'Kind of' means that if I import both classes in the test project like so:
import SubClassA, SubClassB from 'my-package'
and then do:
let sca = new SubClassA()
it turns out to be SubClassB. If I ommit SubClassB from import, it works normally.
EDIT 2 - SOLUTION:
Per instructions in the comments below, I've changed the index.js file like so:
export { default as SubClassA } from './subclasses/SubClassA'
export { default as SubClassB } from './subclasses/SubClassB'
and I imported it in the test project like so:
import { SubClassA, SubClassB } from 'my-project' and it worked.
The problem is you're not exporting anything from your main file,
using es6 import/export syntax you can directly export it with:
export {default as SubclassA} from './subclasses/SubClassA'
export {default as SubclassB} from './subclasses/SubClassB'
then to you can use the named imports :
{SubClassA, SubClassB} from 'my-package'
I got this error in my browser
Error in ./src/App.js
Module not found: ./components/todo in C:\Users\James\Desktop\react\src
This is what I got in my editor
import {TodoForm, TodoList} from './components/todo'
http://imgur.com/a/8YLod
I even tried import {TodoForm, TodoList} from './components/todo/' I wonder what's wrong.
Imports work on a per module basis for most loaders/bundlers. In other words, you'll need to import the form and list by doing the following:
import { TodoForm } from './components/todo/TodoForm'
import { TodoList } from './components/todo/TodoList'
As a side note, see https://developer.mozilla.org/en/docs/web/javascript/reference/statements/export to make sure that you're exporting the components correctly. The curly braces around your import works for a named export as opposed to a default export.
In order to just import all files from the directory you must have an index.js file that exports everything from the directory
Which in your case the index.js file would look like this
Export * from 'TodoForm'
Export * from 'TodoList'
Note if the export statement doesn't work see this answer to fix the import / export statement
Do you think, when you wrote import {TodoForm, TodoList} from './components/todo', in TodoForm should be value than you exported from file TodoForm.js, and similarly with TodoList? It's don't works.
You should do import from some file. When you wrote from './components/todo' you tried doing import from todo directory. I guess, in egghead video that import works, because, they have index.js file in todo directory. And in this file they do export for every component separately. Try to add index.js file in todo directory with the following contents:
export * from './TodoForm.js';
export * from './TodoList.js';
it's will work.
So the thing is that when you do
import {TodoForm, TodoList} from './components/todo'
What happends is that your compiler will by default search the components TodoForm and TodoList from the index.js file since you have not mentioned explicitly which files to point to
So if in index.js you add something like
export * from './components/todo/TodoForm';
export * from './components/todo/TodoList';
Your approach will work.