In my NextJS app, I have node_modules (js files) for themes for certain elements on the page. I want to load only the files I need this based on this.props.theme for the component. How/where would I do this in my component. Basically, if I have a bunch of files for themes:
theme-red.js
theme-orange.js
theme-yellow.js
theme-green.js
theme-blue.js
theme-purple.js
theme-violet.js
theme-pink.js
theme-rainbow.js
In the props, I would this.props.themepassed in and then load in require(theme-${this.props.theme}.js)
You can use the import function:
const theme = await import(./{path-to-the-files}/theme-${this.props.theme}.js)
It would be good to include this in the componentWillMount function of the component.
https://nextjs.org/docs/advanced-features/dynamic-import
https://javascript.info/modules-dynamic-imports
Related
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.
Is it possible to dynamically import precompiled svelte components or whole svelte apps.
And when, how do I compile a single component in svelte 3. I found this approach, but nothing in the docs:
https://github.com/sveltejs/svelte/issues/1576
I want to combine several independent (hosted) Svelte apps on one page to one bigger svelte-app (microfrontend). The goal is, that every sub app can be independent deployed and hosted wherever (may be an own docker container). And any change should be visible in the aggregator app without recompiling it.
I think I wat to do something like this:
https://single-spa.js.org/docs/separating-applications.html
but with no other framework, that is blowing my app and components.
I don't want to use custom components, because of the inflexible styling of the Shadow DOM. I must be able to change css over a global stylesheet.
Has anyone an idea?
Thank you :)
You can take a look at Ara Framework. It has a standalone component named Nova Bridge.
This approach consists of a component that renders a placeholder micro-frontend view will be mounted. Then the component emits a DOM event named NovaMount that is listened by the JavaScript bundle of the micro-frontend to render it and mount it in run-time.
Here an example of the entry point for your micro-frontend.
import { mountComponent, load, loadById } from 'hypernova-svelte'
import Example from './components/Example.svelte'
const render = (name, { node, data }) => {
if (name === 'Example') {
return mountComponent(Example, node, data)
}
}
document.addEventListener('NovaMount', ({ detail }) => {
const { name, id } = detail
const payload = loadById(name, id)
if (payload) {
render(name, payload)
}
})
load('Example').forEach(render.bind(null, 'Example'))
The microfrontend uses hypernova-svelte. You can take a look in this article I wrote for implementing Svelte in Nuxt.
https://ara-framework.github.io/website/blog/2019/08/27/nuxt-js
I'm trying to use dynamic import for importing a different modules depending on the props passed to the component. Paths to the components are kept in an object
const components = {
'apple': './Apple.js',
'orange': './Orange.js',
// ...
}
Then
// ...
import(components[this.props.type])
// ...
Unfortunately, I get the following error:
Unhandled Rejection (Error): Cannot find module './Apple.js'
It disappears when I explicitly specify the filename (import('./Apple.js')). Is it possible to force nextjs to serve these dynamic modules?
You need to use the dynamic utility from next/dynamic for dynamic import in Next.js. This function is inspired by react-loadable library and uses similar syntax.
The simplest way to dynamically import React component in Next.js is:
const DynamicComponent1 = dynamic(import('../components/hello1'))
If you want to import module that is not a React component than you need to use customizing rendering feature:
const DynamicDeliveryOptions = dynamic({
loader: () => import('../components/delivery-options'),
render(props, loaded) {
const options = loaded.deliveryOptions.map(
option => <option key={option.id}>{option.title}</option>
);
return <select>{options}</select>
},
});
Notice that signature of the render function in Next.js is different from
its signature in react-loadable library (props is the first argument in Next.js).
Returning to your example: I think the best way to import multiple modules will be to declare them all as dynamic modules and conditionally render depending on the passed props (modules won't be loaded before render).
You can tell webpack to put a dynamically named module inside a particular chunk using this syntax:
const module = await import(
/* webpackChunkName: "your_custom_chunk_name" */
"path/to/your/module"
);
Webpack will extract your module's code inside the file: /.next/server/chunks/your_custom_chunk_name.js.
(Tested on NextJs version 12.1.6)
I'm planning to build a very dynamic single page website template for Gatsby.
The theme will have many block-types componentes (30 or more) available, like:
Jumbotron
JumboTron2
JumbotronWithForm
MapWide
MapSquare
...
I intend to render the page based on an array of objects, each one having a type (like Jumbotron) to match a component and the necessary data to render it.
If I import all these componentes statically...
import Jumbotron from './../components/Jumbtron';
...they all will be included in the generated JS, which is bad because my JS will be too large.
If I use dynamic imports...
async componentDidMount(){
if(jumbotronTypeRequired){
this.jumbotron = await import('./../components/Jumbotron');
}
this.setState({ dynamicComponentsLoaded: true });
}
render(){
if(this.state.dynamicComponentsLoaded){
//render all
}
else{return (<div>Loading...</div>)}
}
...I can only fetch the component in a Promise, this means that the component will fully rendered after the ComponentDidMount, which is bad for SEO because my resulting HTML will not contain the fully rendered data.
Does Gatsby has a way to include only the necessary components to render the dynamic page while keeping a fully rendered HTML (not just render "Loading...")?
You can use the plugin gatsby-plugin-loadable-components-ssr to achieve this. There will however be a reference to the file path of each component in the bundle but at least the actual components do not get bundled.
I have a node project that creates a static react SPA using:
react-router
redux
postcss
react-css-modules
It currently loads in a global css file and modular css for each component. On start I fetch a global theme var that will be say 'theme-1' or 'theme-2'. I want to load different css files, same name but different directory path, based on the value of the theme var, Eg:
If theme is 'theme-1' then import '/css/themes/theme1/Component.css'.
Else If theme is 'theme-2' then import '/css/themes/theme2/Component.css'.
Any ideas how I could achieve this?
Note that module imports can not be wrapped in an if/else statement as far as I can see.
You could use require:
if(...) {
require('/path/to/theme1.css');
}
else {
require('/path/to/theme2.css');
}