I'm trying to make a website with multiple components where each one is loaded with async import because I don't need every component (and maybe the user hasn't even access to it).
This is an example file structure (mine look somehow like that):
src/
utils/
...
index.ts
components/
home/
...
index.ts
about/
...
index.ts
contact/
...
index.ts
Now I import the needed component somewhere in src/index.ts (I'm using TypeScript). Everything is fine until here.
Now the problem: When I need to use files from utils in a component which is loaded with lazy-loading, is that file bundeled twice? So the first time with the main chunk and the second time with the component chunk? How can I tell Webpack that this file is already included and doesn't have to be bundeled again? So I want to use the same cached version again in a component that is lazy-loaded.
Related
(Code below is a simple example, real scenario is bigger)
I have two modules, mod1.js and mod2.js, which are bundled together (using esbuild). They share a common dependency, util.js.
Problem is: when code in mod2.js imports util.js (using same alias), there's a conflict with names.
util.js:
export class Util {
...
}
mod1.js:
import Util from "./util.js";
...
mod2.js:
/* this raises an error of variable already declared */
import Util from "./util.js";
...
If I change alias in mod2.js, error goes away, as expected. But changing aliases every time I import util.js is a bit clumsy, and makes me think there has to be another way.
Is there a better approach to point to a common dependency from multiple modules which are bundled together?
Thanks in advance!
With help from #Bergi's comment, I figured out that I was not using esbuild to bundle my files, but rather using Hugo to concatenate them, and passing this to esbuild.
This leads to mentioned error because there are multiple imports in the same file, which esbuild correctly doesn't recognize as valid. Instead, using esbuild to bundle my files gives me correct results.
I'm still using Hugo, but I have a single entry point which it consumes, that imports all my scripts. From example, I have another file, say master.js:
master.js:
import mod1 from "./mod1.js";
import mod2 from "./mod2.js";
And I then pass this master.js to Hugo, using its js.Build function, which internally uses esbuild. This way I can import util.js using same alias, because these imports are in separate files, using ES6 linking from esbuild.
I am trying to create an npm package for others to use. Currently, my project looks like this:
lib/
forms/
Button.js
...
layouts/
Row.js
...
node_modules/
src/
forms/
Button.tsx
...
layouts/
Row.tsx
...
package.json
...
package.json specifies that only lib/**/* should be published. An npm script compiles my *.tsx files into the *.js files in the lib/ directory.
Ideally, after someone installs my package, they would be able to import Button like this:
import {Button} from "#whiterook6/components/forms"
But the way the import works currently is if it looks like this:
import {Button} from "#whiterook6/components/lib/forms/Button"
How and where do I put my index.js files, and what content goes inside them, so that they
reference the lib/**/*.js files properly, instead of referencing src/ files, since those won't be published;
allow other devs to only include the bits they want (so the total compiled project size remains small); and
have a "nice" import statement?
Also, what is the correct export syntax I should use?
I am wondering if it is possible to re-configure the import behavior (looking for index.js) on importing module folders directly. By default, when you assume this module folder structure:
/components
/Button
/index.js
/style.scss
/Checkbox
/index.js
/style.scss
I can easily import the components like this:
import Button from 'components/Button';
import Checkbox from 'components/Checkbox';
But when I am working on that components, I will have multiple index.js files open in my editor/ide which will lead to confusion very quickly. Same applies for the style files.
What I did now is changing my folder structure to this:
/components
/Button
/Button.js
/Button.scss
/Checkbox
/Checkbox.js
/Checkbox.scss
Which solved that problem and I can see directly where each opened file belongs to.
However, now my component imports look a bit... verbose:
import Button from 'components/Button/Button';
import Checkbox from 'components/Checkbox/Checkbox';
Because obviously, webpack/babel would look for an "index.js" when I am importing a folder directly. Now my question is: can I change that behavior somehow? I'd like to tell webpack/babel that it should try to import a file named the same way as the folder as the index file.
You can re-configure directory indexes on every webserver, so I am hoping the same is possible with webpack/babel but googling didnt show anything up so far.
I went with the following solution:
In each of my folders, I will create a index.js next to the "real" module, that has the follwing content:
import module from './Button.js';
export default module;
This way I am able to keep my code in Button.js but am not required to import Button/Button someplace else.
I created a little script which automates the creation of the index.js files for me, so I don't have any additional work.
I'm working on a fairly large project using react/webpack with a lot of components.
Currently my folder structure looks like this:
bin/
media/
src/
components/
login/
Login.js
LoginContainer.js
registration/
index.js
..
framework/
redux/
..
static/
test/
And in src/components/index.js I do the exports: export Login from ./Login/Login so that in other components I can just do import {Login, LoginContainer} from 'components' without having to search the file location.
Is there a way to not have the exports in the index.js like now?
I'd like to export automatically all javascript files by their name, without having to type it every time.
You can add (all of) your Components-SubFolders to your webpack.config.resolve and just import the Filename.
Or just add the components root to resolve.modulesDirectories and import the Path relative to the components-folder.
I have this problem, I have these scss files for all my global variables:
colors.scss
fonts.scss
helpers.scss
And I have these scss files for my component based and import it on top of the .jsx files:
header.scss
footer.scss
searchbar.scss
My problem in all of my component based scss files, I need to import the color.scss and helpers.scss in that way it will be included multiple times in header.scss,footer.scss and searchbar.scss
How do you guys work on it, been searching for an hour and did not found any solutions.
Thanks!
Just make a app.scss file and import all the scss files into that one starting with your variable files.
We do a similar thing at my work and have one file that we import all our component scss files into and any shared dependencies go above those that way you are only having to import once. The main thing is to make sure that files with dependencies go below the dependency files.
Create a global scss like so:
global.scss => imports colors.scss, fonts.scss, helpers.scss
and include it in your root JS file.
This way, every time you create a module, it will have these default styles.