react, webpack: avoid ".." in import statements - javascript

I'm currently learning react and thus es6/es7 and webpack.
Coming from a largely python background I'm annoyed by the folder sensitive path declarations for import statements, i.e. the use of ../../ in import statements. This means if I move a file to a different directory, i need to change the import statements declared in the file.
Python's import statement doesn't have this issue. I'd like to mimic that behavior
(search first a particular directory for this path, if not search this other base directory)
e.g. if i have the directory structure
myApp
components
component1.jsx
stores
store1.jsx
views
view1.jsx
node_modules
react
etc
in my view1.jsx I don't want to write
import Component1 from '../components/component1'
I want to write
import Component1 from 'components/component1'
or maybe even
import Component1 from 'myApp/components/component1'
just to make sure I don't have name collisions with some npm package I may be using.
What is the correct way of accomplishing this in webpack? Is it using alias?

I ended up following #zerkms recommendation. resolve.modulesDirectories is the way to go.

I wrote a loader to accomplish this, https://www.npmjs.com/package/future-require-loader. It will autoload a path anywhere three underscores surround a partial file path ___filename.js___. it also allows folder paths: ___folder/filename.js___. it will attempt to match the first file path that includes the string so you will want to include folders if there could be a conflict.

Related

Best practice for importing component from components library in React.js

When I create components in React, they're all in a folder called component and each component has a dedicated folder with the same name as the component itself, e.g. ../components/Input.
But a big concern is about naming files. In order to avoid having to long paths, I name the component inside the folder Index.tsx so that when I import, I'll only have ../components/Input otherwise, it would be a very ugly import path like ../components/Input/Input.
So, by naming Index.tsx, in my IDE, I end up having too much index files open and then I get lost.
So what I did was to rename all those components file with the same name as the folder Input.tsx and exporting them using named export like export const Input:React.FC<InputProps>=(props)=>{...}, then at the root of my component folder, I created one index.tsx file where I export all those components so that while importing them in my pages, I can just write import {Input} from "../components".
I like this approach, but my next concern is about tree shaking. Because I don't want to import every time the entire components library.
So with the above approach, does React handle automatically tree shaking for us?
There's a tweet about the possible issues related to re-exporting everything with index files.
If your project has a components/index.js file which re-exports all your components (and does nothing else), that’s one example.
This is bad for performance – for two reasons.
It makes code splitting ineffective.
When you do
import { Button } from './components'
you’re importing not only Button but the whole ‘./components’ file. Which means you’re bundling the whole file – with all the components it exports.
It makes bundle initialization more expensive.
Every time a browser downloads the bundle, it has to execute it – and all its modules as well. If there’re a lot of modules, or some of them do something expensive, this can take a while.
Someone else suggests configuring webpack's sideEffects option so that the tree-shaking can still optimize the bundle as much as possible.
What I'm suggesting is to create small component modules inside the components directory.
- components/
- Input/ # component module
- index.ts # exports public API
- Input.tsx # actual component implementation
- Input.test.tsx
- Input.scss
- Input.stories.tsx
- etc.
Where the index.ts only re-export the public API for this component.
// index.ts
export { Input } from './Input';
export type { InputProps } from './Input';
// etc.
So that we have non-repeating paths when importing, but the filename we're actually working with is named according to the component.

ES6 Modules - 3 ways of importing files

Hello guys i have a little question about importing files into a single .js file.
Which way is better (best practice), what's the scenario that is used for:
import './file;'
import { something } from './file'
import * as evertything from './file'
Because i see that 2 and 3 are the same thing but different syntax(maybe Syntactic Sugar).
All three do different things.
import './file;'
That loads the file, and does not import anything. This is useful if you want to initialize that module (or add some external dependency, e.g. a css file if you use Webpack).
import { something } from './file'
That just imports something from the file, therefore a bundler could optimize all other dependencies away. I'd always try to go with that instead of
import * as evertything from './file'
That imports everything from that module under a namespace, and therefore makes treeshaking more difficult (the bundler cannot optimize it well). I'd only use that if you need everything from that dependency, or if that dependency is loaded externally nevertheless (e.g. import * as React from "react").
I guess the following MDN documentation will make you clear about those things:
import - JavaScript|MDN
As far as I know, 1st method is used when you have only one default export. 2nd is used when you have multiple default exports but you don't want all of them to load and want only few of them. 3rd is the case when you want everything under a single object (which can be used similar to namespace in other programming languages).

How to export multiple library variants from a single NPM package

I'm creating a node library that could be partially used in web browsers.
My current structure is something like:
package.json
lib/
index.js
node.js
web.js
modules/
some-function.js
some-node-function.js
some-web-function.js
...
"lib/index.js" is specified as "main" in package.json
I'm using each file inside lib/ to re-export functions from modules/ filtered by target (all/node/web)
And I would like to use it like this:
import fullLibrary from "my-library";
import {someFunction} from "my-library";
import webOnlyLibrary from "my-library/web";
import {someWebFunction} from "my-library/web";
import nodeOnlyLibrary from "my-library/node";
import {someNodeFunction} from "my-library/node";
BUT keeping index.js, node.js and web.js inside /lib!
Currently only the first two import statements work (because index.js is pointed from package.json).
I know that I could place those files in the root of the package and it would work as expected when importing, but I was wondering if there was a way to do the same while keeping the files in /lib for cleanness.
In any case, is this the recommended way to expose multiple variants of a same library from a single NPM package?
Just for anyone that is having similar questions regarding libraries structure and organization.
Back then I started working with monorepos using Lerna and Yarn Workspaces and I haven't regret it. I think this is the most efficient way to go in terms of modularity, readability, scalability and maintainability.
Specifically, the question code would be traduced into this:
import webOnlyLibrary from "#my-library/web";
import {someWebFunction} from "#my-library/web";
import nodeOnlyLibrary from "#my-library/node";
import {someNodeFunction} from "#my-library/node";

ES6 Module directory structure

I didn't find anything on Google but I'm wondering if there's a "best practise" of structuring an ES6 project in terms of directories and module exports.
Currently I do have two different ways in mind:
Using an index.js for every module and export everything:
app.js
modules/
ModuleName/
ModuleFile.js
index.js
ModuleFile.js would look something like export class ModuleFile { }, the index.js would be simply
export * from 'ModuleFile'
This makes it possible to import files with import {ModuleFile} from 'modules/ModuleName'. Readable, but requires an index.js for every module, even if the module has just one single file.
Second approach would be without using index.js files, but that would mean import statements would become slightly redundant import {ModuleFile} from 'modules/ModuleName/ModuleFile'.
Are there any best practises on this topic?
Your approach seems fine, I don't see a problem with it. In two different projects I've worked (different companies) it was the pattern used.
You could also put the ModuleFile.js content directly in index.js:
app.js
modules/
ModuleName/
index.js
Or create a file directly for a module:
app.js
modules/
moduleName.js
In cases only a "file" is necessary. The evident problem is that changes or the growth of the module may force this structure to change. There would also be an inconsistence in terms of structure with other modules.

Javascript ES6 import without a name [duplicate]

This question already has answers here:
import module just to run it
(2 answers)
Closed 6 years ago.
I am running Webpack, Babel and Vue.js and I want to split up my entry file. Currently I have an app.js file which is the starting point to my application.
I have some bits and pieces of Code I want to put into a bootstrap.js file which I want to include in my main app.js file can I can have a clean file to start out with Vue and add components in it as I go.
Some examples of what I would want to put in my bootstrap.js file:
import messagesNL from './translations/nl';
Vue.use(VeeValidate, {
locale: 'nl',
dictionary: {
nl: {
messages: messagesNL
}
}
});
window.Vue = Vue;
So pretty much setup for plugins, global configuration, etc. I feel like this is not your typical module and I find it hard to create a module like structure for this file so I basically use this in my app.js file:
import bootstrap from './bootstrap';
Having no idea if this would work, it seems to just import everything neatly without me having done a module exports {} like syntax.
Now the bootstrap variable that I assigned to that file is unused in app.js since it's only used to require the file and my IDE kind of 'greys` it out to let me know it is unused.
Is there another syntax for this so that I don't have to assign a name to it? Is this approach ok to split up my file, or should I be doing something else?
I haven't put it into a proper module yet because then it would have it's own local scope and I would be unsure how to set up Vue with all the plugins, etc. If anybody has a better suggestion I am open to it.
Cheers.
To include a file without importing anything you can just drop the <name> from part of the statement:
import './bootstrap';
This will execute the target module without affecting the scope of the active module, but it may have side-effects such as declaring globals or modifying existing globals.
As stated in the MDN docs for Import a module for its side effects only:
Import an entire module for side effects only, without importing anything. This runs the module's global code, but doesn't actually import any values.
import '/modules/my-module.js';

Categories

Resources