ES6 Modules - 3 ways of importing files - javascript

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).

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.

Importing distant modules in javascript from unpkg

I’m trying to import whole modules in a javascript file.
This file pertains to the Home Assistant environment where the frontend is written in javascript, usually using LitElements and modules (cf. documentation).
For instance, the doc uses a fancy wired-card by writing:
import "https://unpkg.com/wired-card#0.8.1/wired-card.js?module";.
I've read a lot about the import call but resources are usually about local elements and it seems that I need them to be distant.
In fact, I know the plain old JS quite well but I am a bit clueless regarding importing modules (and LitElements for that matter).
For instance, I'm looking for an accordion (expansion panel), like the one of JQueryUI. I found several resources (e.g. here, here, or here) but I couldn't find how to import them easily.
What makes a module importable? Are those not or am I doing it wrong?
In standard ECMAscript, a JS file is importable if it defines a module in the new system. Kinda circular.
Basically, it should export some resources from the module file. For example, if I have a test-module.js, I can export some class using the export keyword:
class Fubar {}
export { Fubar }
// or, more concisely
export class Fubar {}
The export keyword tells the module system that the resource defined should be made available to importers.
On the flip side, if you want to import a module, you must also do so from a module! This is because module imports are async and processed before the execution (excluding the dynamic import() function).
So, if I want to import my Fubar class from another module, I can do this:
import { Fubar } from './test-module.js`
However, if I load this script as a non-module, I will get an error. Instead, I must tell the browser that the script is a module:
<script type="module" src="test-module.js"></script>
So, in short, something is "importable" if it is itself a module.
More reading:
Mozilla Dev Network article on the modules system: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
MDN article on the import keyword: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
EDIT: something I missed - to make web resources a little nicer, the import URLs can be any URL, not just a relative path. This allows importing 3rd party scripts as modules. But, those 3rd party scripts need to be modules themselves.

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';

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

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.

ES6 import module as an object

I am using this GULP plugin which converts HTML files into ES6 exports so I could load them on the browser in my MVC (using rollup bundler).
Basically I have page controllers which are exported as modules.
Then, in my main JS file, I just import all the page controllers, once by one, like so (simplified):
import * as page__home from './pages/page1';
import * as page__home from './pages/page2';
...
Since this is an SPA, I would think it would be easier to somehow import all the page controllers into some object, so then when a controller is to be called, I could check if that name exist in that object which holds all the imported controllers, or something like that.
Or maybe there is a way to check if a module was imported somehow?
Is there any smarter way of doing this? Thanks
As noted above:
I think I got it actually, I will combine all the controllers files using gulp, then import that one file, and it will all be under that namespace, like so import * as pages from './pages/bundle'; then I could check if( pages["xxx"] )

Categories

Resources