How do I use CSS Houdini in Next.js - css

I would like to use CSS Houdini in a Next.js project I am building. I have installed, via yarn, both the CSS Houdini package I want to use along with css-paint-polyfill. I am following the webpack instructions here https://houdini.how/usage
Here is my component:
import 'css-paint-polyfill';
import workletURL from 'url-loader!css-houdini-lines';
import styles from './Separator.module.css';
CSS.paintWorklet.addModule(workletURL);
export default function Separator() {
return <div className={styles.separator} />;
}
I am getting the dreaded
error - ReferenceError: window is not defined
at /home/tithos/code/web/new-tim/node_modules/css-paint-polyfill/dist/css-paint-polyfill.js:1:239
I tried putting the import for css-paint-polyfill in a useEffect, but the throw another error. I even tried const DynamicComponent = dynamic(() => import('../components/hello')) from https://nextjs.org/docs/advanced-features/dynamic-import, but I did not know how to reference the library.
Has any one solved this?

Seems like CSS Paint Polyfill eagerly accesses window, which means it will throw an error when in an environment which has no window, such as server phase of Next. There are multiple things you can do.
Modify your next.config.js to stub the aforementioned module when for Webpack when isServer is true. You can follow this page of the Next docs for this.
Create a dynamic component that's only imported on the client (I see you've tried this, but it should have worked, so maybe if you shared what you did in this regard, I could work out what's wrong with your approach).
Create an issue and send in a PR to the repository where the Polyfill is hosted to lazily access window depending on whether it's available or not.

Related

Imported modules without server side rendering feature

I have an issue with Next.js. When I'm trying to import a node module,
the module uses the window object and Next.js is throwing an error: window is not defined.
The module is imported like this:
import * as widgets from 'survey-widgets';
widgets.autocomplete(Survey);
I guess Next.js dynamic imports will not work in my case. Is there any way of doing it?
Try deferring all the code that uses window or any other api that is restricted to the browser, in useEffect, because the code in useEffect only runs in the browser.
If you can't do that, then make an intermediary module which you will use to import survey-widgets and re-export what you need. So in the end, you import that intermediary module dynamically.
import * as widgets from 'survey-widgets
export default widgets
For anyone looking for the solution for this, I solved it with NextJs Dynamic imports with no SSR.
What I did instead is importing my top level component using dynamic import like this:
const MyComponent= dynamic(
() => import('../components/hello3'),
{ ssr: false }
)
So the hello3 component will no longer be used in server side rendering and instead it will render on client side.
Then just use it like this:
<MyComponent/>

Fomantic UI - TypeError: $(...).toast is not a function

I am using Meteor with React and Semantic-ui-react. I needed a toast function so I wanted to change to Fomantic UI. Everything related is loaded by NPM.
I removed semantic-ui-css and added fomantic-ui-css.
I removed the
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/semantic-ui#2.4.2/dist/semantic.min.css" /> from the head.
I changed all import 'semantic-ui-css/semantic.min.css'; to import 'fomantic-ui-css/semantic.css';
When I try to execute a
$('body')
.toast({
title: 'LOOK',
message: 'See, how long i will last',
showProgress: 'bottom'
})
;
I get TypeError: $(...).toast is not a function
I can't find anything on it over various searches through SO and repository issues.
Thanks for any help you can give!!
Phil
You basically need to import the semantic.js file, which will add the functionality to your jquery instances:
import 'fomantic-ui-css/semantic.js'
import 'fomantic-ui-css/semantic.css'
However, there is no need to import the .min.* minified files, because Meteor will use a js and css minifier when you build your app for production / deployment later.

How do I include the same Web Component dependency in multiple Components without "duplicate registry" error

I am making a lib similar to Polymer Material. I have individual files I use rollup to create a single ESM, CJS, and UMD file. The ESM file is the main in the package.json. I have a situation like this
Header
Icon-Button
Icon-Button
The icon button Uses Mustache so I need to include it using the rollup-plugin-node-resolve. I then import the library in Header and create a UMD file that is imported into my we app like this...
// Pug
script(src="/ui-components/header/dist/index.umd.js")
script(src="/ui-components/icon-button/dist/index.umd.js")
// Express
// #me/icon-button
// #me/header
const uiPath = path.join(__dirname, './node_modules/#me');
app.use('/ui-components', express.static(uiPath));
I get the following in the browser console on load...
Failed to execute 'define' on 'CustomElementRegistry': the name "me-icon-button" has already been used with this registry
How do libraries handle this? I thought about removing the resolve plugin for mustache and assuming it is included globally. However, it seems pretty onerous to make everyone find a way to import mustache into window and not something most libraries do. I could also do something like this question suggests...
customElements.get("me-icon-button")||customElements.define("me-icon-button", IconButton, {...});
But having that multiple times in my code does not seem right either.
So How do I include multiple web components that reference other similar components?

Import a js file from node_module inside twig

I have an import issue I can't understand, but I think I'm missing something big with either webpack or Symfony and I can't find what.
I hope you can tell me.
I try to use the reveal.js module. So, using npm I added the content of this github to my node_modules: https://github.com/hakimel/reveal.js/
Without looking at Symfony, only the index.html from the reveal.js module. There is an import line <script src="js/reveal.js"></script>
If this import is missing, then an error occured: Uncaught ReferenceError: Reveal is not defined
But with this import, all works fine.
If I'm telling you about this simple index.html, it's because I have the same error in my Symfony project, and I can't tell why because I think my imports are fine.
So either, my import is not ok...either the error is not the same, but I can't tell where she is.
In my webpack.config.js, I have this
.addEntry('js/app', [
'./assets/js/app.js',
'./node_modules/jquery/dist/jquery.slim.js',
'./node_modules/popper.js/dist/popper.min.js',
'./node_modules/bootstrap/dist/js/bootstrap.min.js',
'./node_modules/holderjs/holder.min.js',
'./node_modules/reveal.js/lib/js/head.min.js',
'./node_modules/reveal.js/js/reveal.js'
])
As you can see, the reveal.js file is there, so he is concatenate into my main js file. But still, I have this Uncaught ReferenceError: Reveal is not defined when I try to use <script>Reveal.initialize();</script> inside of a twig template.
I'm really lost for this moment, so I hope you can help one way or an other, thanks :(
EDIT: In order to add some information, in my build/app.js I can see the import is there.
/***/ "./node_modules/reveal.js/js/reveal.js":
/*!*********************************************!*\
!*** ./node_modules/reveal.js/js/reveal.js ***!
\*********************************************/

Webpack Encore select2 not working with not a function import error

Using Symfony 4 and Webpack Encore, I can't get Select2 to work.
I'm using select2#4.0.3 and importing it this way in app.js:
import $ from 'jquery';
import 'bootstrap';
import 'select2';
I also tried to use
Encore.autoProvidejQuery()
in webpack.config.js, then taking care of commenting the
import $ from 'jquery';
line in app.js so that jquery is not imported twice.
I tried everything I could find in other answsers like:
import select2 form 'select2';
$(() => {
$('.select2-enable').select2();
});
or
select2($);
Almost all my attempts result in the same error:
TypeError: $(...).select2 is not a function
EDIT:
Working now. Everytime I made a change in app.js (and rebuilt) I used the firefox devtool console to check if it was working but I always got the
not a function
error even though the problem was solved and select2 was working.
Is this because I'm using Webpack that the browser console doesn't recognize the select2() function anymore?
First install it using yarn:
yarn add select2
Then use it with require instead of import:
require('select2')
at your app.js file.
It works the same using require or import.
Babel converts import and export declaration to CommonJS (require) which lets you load modules dynamically.
So, despite of them looking the same, try to always use require.

Resources