Next.js use of _app.js and _document.js - next.js

I currently use _document.js to inject css into my Next.js app and I would like to start using _app.js to help inject data into pages.
Was wondering if it possible to use _document and _app in tandem or should we only use one or the other?

Short answer: Yes, You can use both. They serve different purpose and can be used in the same application.
According to NextJS docs:
Next.js uses the App component to initialize pages.
To override, create the ./pages/_app.js file and override the App class
and
Pages in Next.js skip the definition of the surrounding document's markup. For example, you never include <html>, <body>, etc. To override that default behavior, you must create a file at ./pages/_document.js, where you can extend the Document class.
Note: _document.js is only rendered on the server side and not on the client side. so event handlers like onClick is not going to work.

Related

Conditional stylesheet in Nuxt SSR depending on a store value

I've been surfing StackOverflow and the Nuxt documentation, but I cannot get my head around this one.
So, I need to do RTL. My project is in Nuxt and we use SCSS. I'm setting the htmlAttrs to dir="rtl" conditionally depending on a store getter that tells me if the language is RTL or not. The requirement for this specific task is that a RTL stylesheet should be imported conditionally from the server side also if the country is RTL, so that it overrides the main.scss file.
Now, in nuxtServerInit(), I cannot set the stylesheet in the head, because the route will not direct me to the file, and, most importantly, Webpack won't compile it, as it's outside the regular flow of the application and not imported by main.scss, which is the stylesheet the Nuxt config is pointing to, and which contains all other styles. I realize that I could use a class and use it conditionally in components, but that is not the requirement. The nuxt.config.js file, in the relevant part, looks like this:
css: [
'#/assets/styles/main.scss'
]
There I obviously don't have access to the store.
What I said I tried was this:
if (isRTL) {
service.addEntryToArray('link', {
rel: 'stylesheet',
type: 'text/css',
href: '../assets/styles/main.rtl.scss'
});
}
(We use a service to add things to the head)
I understand that was naive on my part, because Webpack has no say there, so there is no transpilation, and there is no actual asset, which means the route is just wrong, and even if it were right, the browser would not be able to read it.
Any ideas on how this could be achieved at a non-component level? This needs to be part of the Webpack flow, has to be added server-side, and needs to be an import --I cannot just import it regularly and use just a class (again, I'm not stubborn, I'm working on a project, and this is a requirement by the client).
If you need more information, I'll update the post, but I don't know what else to provide.

Using third party libraries in Svelte custom component

I want to create a web component using svelte. To create a web component it's necessary to include the svelte tag option
<svelte:options tag="{"my-custom-component}"></svelte:options>
It creates a custom component with that name but doesn't work properly because we have to provide this tag for all the child components as well! I added it to all the child components but it still doesn't work, turns out I use third-party libraries and I don't know any way to have that option there!
Is there a way to create the custom components with svelte which includes third-party libraries?
You can use regular svelte components (including third party) ones inside your component.
But you'll need to compile those with different compiler settings in your rollup/webpack config.
And due to the nature of scoped styling in web components (Shadow DOM) the css won't work in these components. So it depends on the library if it still works.
You might be able to turn off scoped styling in the future:
Issue #1748: Custom element without shadow DOM
But scoped styling could have been the reason why you wanted/needed webcomponents in the first place.

Page specific css not loading

I use nativescript with VueJs
My problem is that my page specified CSS files aren't used.
My start page is start.js and in the same folder I have a start.css
but the styles aren't applied.
Do I need to something else, or configure?
Because at the docs I said that it normally should work like this.
Always refer the appropriate docs for the flavour, since you are using Vue you must follow the docs here. What you were referring to was for core js one.
With NativeScript Vue you have to write scoped styles within your component, just the same way how you would do it for a Vue based web app.
An external file can be used as Page-Specific CSS as follows in NativeScript-Vue:
<style scoped src="./Home.css"></style>
Where, Home.css is located in your components folder.
Similarly, for SCSS:
<style lang="scss" scoped src="./Home.scss"></style>
Note: You'll need to rebuild your app by if its running on an emulator/device when you make this addition to your .Vue file.

Web components and shared styles

This is one of those "what should we do about this"-questions. As you know, web components are supposed to be small, contained applications for websites. However, sometimes these needs to be styled depending on the site they're embedded on.
Example: "Sign up to our newsletter"-component. This component would have a few key items:
An input box
A button
Maybe recaptcha
A method that talks to your service once the button is pressed (passing in the email)
We're going to use Google and YouTube as examples. Google's color scheme is blue (let's imagine that) and YouTube's color scheme is red. The component would then be something like <newsletter-signup></newsletter-signup> on the page you're embedding it in. Both Google and YouTube have this.
The problem comes in, when the component needs to inherit the styles from Google and YouTube. A few deprecated CSS selectors would be great for this, because Google and YouTube's style sheets could simply enable colors for the Shadow DOM, so we wouldn't have to copy/paste the styles. The component should theoretically not know anything about the styles from the host, because we want it to inherit from the host (Google and YouTube).
At the moment, I'm creating a web component using Angular 6, which has a lot of styles, because it has a lot of elements. I'm copy/pasting styles, Bootstrap, icons, and so on from the host site, then styling them based on <newsletter-signup brand="google"></newsletter-signup>. So if the brand is Google, the colors should be red, for example.
This is really bad, because of a few reasons:
Styles have to be updated on both the web component and on the host
Duplicated code is never a good idea
If all the styles are copied 1:1, the amount of bytes required for styles is doubled
How would I, as a developer, take this into account? How do I make styles on the host, then apply them on my web component (call it inheritance)? I'm sure someone has had the exact same problem with Shadow DOM as I am experiencing. Thanks for reading.
I realize you do not want to write same kind of rules for your common component(selector)
i.e. you want to do styling as where your common selector is placed.
Things you can do to handle this:
1. Create your own logical css framework
Write most commonly used CSS rules in global css.For example if you have integrated bootstrap and you want to override bootstrap, you will write most common overrides in app.css which overrides bootstrap.
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"src/styles/app.scss"
],
This app.scss should be written in way to which you can override.
Send Rules as input
send custom rules Obj and use in elements you want to override.
<newsletter [input]="customRulesObj"></newsletter>
component.ts
customRulesObj = new CustomRulesClass();
customRulesObj.color = 'red';
You can send rules in input in various component by creating a common class
as you know where you are embedding this component.
Extend this component from a common component
If you are too concerned for css you can extend your component from a common component which provides you with css logic as per need.
export class NewsLetterComponent extends CSSComponent implements OnInit
{
}
css-component.ts
In this component can logically define css as per host, current routerlink and
other multiple if else condition.
You can define rules by switch case conditions and bind those rules to component you have extended.
One of the biggest must-do's of web components is: My host (page where I'm embedding my web component) should not depend on the web component nor know about the web component.
What this basically means: Styles of my web component should not be shared with the host.
If my host decides to update the styles, it should affect my web component. Not the other way around. To solve this, I imported the external styles from my host directly inside the CSS file using #import. Here's an example:
import url("https://my-host.com/styles/core.css");
my-component {
//all styles goes here
}
I did this using SASS but can be done using regular CSS.
This is not a great solution at all, but it does what I want: Inherit the styles from the host. Although I would have to import every stylesheet there is, it still works.
A downside to my solution: When I load the page, it will send a request to the style from the <link> element inside the <head>-tag my host, but also to the style inside my import. So the styles are loaded twice. For our application, which is internal use only, it doesn't matter if we request additional ~200 KB data.
This question is a few years old and the situation has changed. The way to share styles with web components is now to use link tags to a shared stylesheet.
Inside each component:
<link rel="stylesheet" href="https://my-host.com/styles/core.css">
Reference:
https://github.com/WICG/webcomponents/issues/628

How to inject the style of Vue components into iframe?

How to inject the style of Vue components into the iframe. (for both standard components and async compoents)
I'm making an vue app which is a html5 widget load with js.
In my app, most of js and css are using in iframes, and they rely on the parent window's objects.
Unlike most iframe apps, It dose not load with an url but is made by vue components (just like this forum thread https://forum.vuejs.org/t/render-inside-iframe/6419)
I'm using some workarounds such as cssinjs, inject raw css into iframe within js logic. It should split styles to a single out of .vue file in my way.
Is there a proper way to to that?
Some relates:
https://github.com/webpack-contrib/style-loader/pull/146
https://forum.vuejs.org/t/render-inside-iframe/6419

Resources