import external js into only one component - javascript

When I import external js into angular 4 one component, In every component it will load. How can I import that js file into only one component and how load it when only function call.
//custom component
import * as extjs from '../assets/extjs.js';
constructor(){
this.myfunction();
}
myfunction(){
extjs.extfunc();
}

The reason is when you import your module, it will be injected directly into the app.js file of angular. So, all module can use it.
For instance, when you do this to another component:
declare var extjs: any;
console.log(extjs);
Your extjs return exts api.
So I recommand you to use dynamic import, so your extjs will be ejected only when the component need to use it.
How to do it?
In the file tsconfig.app.json into your folder src, change the following line:
"module": "es2015"
With this line:
"module": "esnext"
It will allow you to make lazy loading script.
So in your component, just do this:
constructor(){
this.myfunction();
}
async myfunction(){
const extjs = await import('../assets/extjs.js');
extjs.extfunc();
}
Check your network tab into your dev tool, load this component or inject it into another component and you will see the chunk of extjs is generated.
Hope it helps you.

You would need something like a dynamic import, so the import can be moved to the function and only executed when necessary. Currently, this is not really well supported, if at all.

Related

How are the imports implemented in different React libraries and how can I implement the same pattern in my own library?

For example, the recommended way of importing in React Bootstrap is to go this way:
import Button from 'react-bootstrap/Button' instead of import { Button } from 'react-bootstrap';
The reason is "Doing so pulls in only the specific components that you use, which can significantly reduce the amount of code you end up sending to the client."
source: https://react-bootstrap.github.io/getting-started/introduction/
Same for React MUI components:
import Button from '#mui/material/Button';
source: https://mui.com/material-ui/getting-started/usage/
I want to implement something similar in my React components library, to limit the usage of code in the bundle, but I don't know how they implement this specific pattern. I have looked at their code base, but I don't quite understand.
Basically it is all about modules and module files and their organization. You can have a lot of.. lets call them folders, "compoments/*" for example. "components/button", "components/alert", "component/badge", and other things. All of them will have some index.js or .ts file that will export or declare and export all the functionality that needed in order to make this component work, 'react-bootstrap/Button' for example. Ideally all those subfolders or submodules are independend from each other, no references between them but probably each one will have 1 reference to 1 common/shared submodule like "components/common" which will contain some constants, for example, and no references to other files. At the top level of them you will have another index.js or .ts file that is referencing all of those components, so "components/index.js" will import and reexport all the nested components index files. So in order to import a Button, for example, you can either import "components/index.js" file with all the other imports this file is using, either only 1 single "components/button/index.js" file which is obviously much more easy to fetch. Just imagine a tree data structure, you import root of the tree (root index.js) - you get all the tree nodes. You import one specific Node (components/button/index.js) of the tree - just load all the childs (imports) of that node.
Sorry for a long read but asuming you mentioned webpack - there is a technique called tree-shaking which will cut off all the unused things.
Info about modules: https://www.w3schools.com/js/js_modules.asp
Info about Tree-Shaking: https://webpack.js.org/guides/tree-shaking/
It might not be as complicated as you think. Let's say you write the following library:
// your-library.js
const A = 22
const B = 33
export function getA () { return A }
export function getB () { return B }
export function APlusB () { return A + B }
// a lot of other stuff here
If some consumer of your library wants to make use of the APlusB function, they must do the following:
// their-website.js
import { APlusB } from 'your-library'
const C = APlusB()
However, depending on how the code is bundled, they may or may not wind up with the entire your-library file in their web bundle. Modern bundling tools like Webpack may provide tree shaking to eliminate dead code, but this should be considered an additional optimization that the API consumer can opt into rather than a core behavior of the import spec.
To make your library more flexible, you can split up independent functions or chunks of functionality into their own files while still providing a full bundle for users who prefer that option. For example:
// your-library/constants.js
export const A = 22
export const B = 33
// your-library/aplusb.js
import { A, B } from 'constants'
export default function APlusB () { return A + B }
// your-library/index.js
// instead of declaring everything in one file, export it from each module
export * from 'constants'
export { default as APlusB } from 'aplusb'
// more exports here
For distribution purposes you can package your library like so:
your-library
|__aplusb.js
|__constants.js
|__index.js
You mentioned react-bootstrap and you can see this exact pattern in their file structure:
https://github.com/react-bootstrap/react-bootstrap/tree/master/src
and you can see they aggregate and re-export modules in their index file here:
https://github.com/react-bootstrap/react-bootstrap/blob/master/src/index.tsx
Essentially, what you are asking is:
"How to export react components"
OR
"How are react components exported to be able to use it in a different react project ?"
Now coming to your actual question:
import Button from 'react-bootstrap/Button' instead of import { Button } from 'react-bootstrap';
The reason is 'Button' component is the default export of that file react-bootstrap/Button.tsx. So there is no need for destructuring a specific component.
If you export multiple components/ functions out of a file, only 1 of them can be a default export.
If you have only 1 export in a file you can make it the default export.
Consider the file project/elements.js
export default function Button(){
// Implementation of custom button component
}
export function Link(){
// Implementation of custom Link component
}
function Image(){
// Implementation of custom Image component
}
Notice that the Button component has 'default' as a keyword and the Link component doesn't.
The Image component can't even be imported and can only be used by other functions/components in the same file.
Now in project/index.js
import 'Button', {Link} from './elements.js'
As Button component is the default export its possible to import without destructuring and as Link component is a regular export, I have to destructure it for importing.

Is there a clean way of importing modules?

I am currently working on a project where I have to import a file to my index.js file.
Here's a snippet:
import './inspector'
import { openSidebar, collapse } from './inspector'
I would like to import everything from the inspector.js in order to run more logic inside that file and at the same time importing openSidebar and collapse function inside it. But I noticed that I'm getting an eslint error no-duplicate-imports in my editor.
How to resolve this issue? I'm still learning on how importing in javascript fully works. I was thinking that maybe removing one of the imports will still work. Thank you in advance.
All of a module's code will run whenever the module is imported, no matter what gets imported - even if nothing is imported. Given the following module:
// inspector.js
console.log('running inspector');
export const openSidebar = () => console.log('opening sidebar');
export const collapse = () => console.log('collapsing');
The following code would successfully log running inspector (in addition to whatever other code existed on the top level of that module):
import './inspector';
The following line would also log it:
import { openSidebar, collapse } from './inspector';
So you should be able to use just that version above, which will run the top level code and import the required values from the module.

prismjs not working between different routes using vuerouter in vuejs

I've imported prism.js globally in main.js file.
Code block syntax highlighting working fine in Home components, but after routing to another page using vue-router, there is no effect.
in main.js
// Global Import
import 'prismjs/prism.js'
import 'prismjs/components/prism-swift.min.js' // swift lang
import './theme/prism-swift-theme.css'
in my about page component...
<pre><code class="language-swift">
private func setupSubviews() {
let value = "Loading code block";
}
</code></pre>
Unable to understand what's wrong here. Is there any way I can import node_modules prismjs files globally? I thought keeping main.js will work fine, but it's not adding globally between routes...
Once you install it with npm the best approach is to import it whenever it is used in each component seperately with import Prism from 'prismjs'. Just make sure to use the Prism.highlightAll() method in the component where you're using prism after the DOM is rendered whether in mount() hook or in the updated Vuejs hook using nextTick method to make sure all the DOM is rendered before using prism. So in your case you should use it this way:
import Prism from "prismjs"
updated: function () {
this.$nextTick(function () {
Prism.highlightAll();
})
}
make sure you call highlightAll in yor components seperately and not globaly.

Bundle VueJS Components to use same data

I'm trying to figure out how I can bundle some Components which use the same data (from an API) so I only need to make one call. I'm learning VueJS right now and I don't know if this is even possible or how it is called. So basicly what I'm trying to archive is this:
Create an index.js file which get's the data from the API and bundles the components which use this data (or parts of it).
Useing import {subComponent} from '#/components/bundle/' to get a specific component from that bundle while it uses the data delivered by index.js
Is this possible? Probably this is common but I don't know what it's called. How can I realize this?
So far I tried this:
view.vue:
<template>
<subComponent1/>
</template>
<script>
import {subComponent1} from '#/components/bundle';
export default {
name: 'view',
components: {
subComponent1
},
</script>
index.js (in components/bundle/):
<script>
import subComponent1 from './subComponent1'
import subComponent2 from './subComponent2'
export {
subComponent1 ,
subComponent2
}
</script>
The Components are standart single-file components and don't use data from index.js yet, but I'm already getting this error:
What am I doing wrong?

Import external js File in Angular 4 and access functions and variables

Maybe my title is a bit unclear, so I will try to explain my problem with a simple task.
Lets say I have a the following Javascript File "file.js":
var number = 4;
function encode(){
console.log("encode in "file.js" has been called...");
}
I place this script in my angular4 project in "src/assets/js/file.js".
In ".angular-cli.json" I add the path of the script
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"./assets/js/modernizr.js",
"./assets/js/webflow.js",
"./assets/js/file.js"
Now my question is how can import or use this script file in my app.module.ts or any other component, without adding it to index.html
I tried several ways:
import * as test from 'assets/js/file.js';
import {test} from 'assets/js/file.js';
declare var file: any;
Unfortunately, none worked...
I would really appreciated it, if you guys could help me out.
You can use system.js to import file at runtime as below, you have to add systemjs in node_modules.
System.import("src/assets/js/file.js").then(fileInstance => {
console.log(fileInstance);
});
In component.ts you should declare the name of the function you want to use.
declare let encode:any
ngOnInit(){
encode()
}
You can Import js locally to ts file like this : import '../../../scripts/custom.js';
then declare method name in custom.js that you want to use like this 👍
declare var fAlert;
then in a place like ngOnInit directly use this method
fAlert();

Categories