SvelteKit(ViteJS) + TailwindCSS not hot reloading components - tailwind-css

I'm trying to code an app using TailwindCSS and SvelteKit, which uses ViteJS under the hood, and while coding I realized that my Header component that is inside ./src/components/common/Header.svelte was not hot reloading on changes. No matter how big or small the change to the component, Svelte would not display them until I terminated script in the console and re-ran npm run dev.
The normal behaviour would be that the whole page updated WITH changes to the components other than pages.
Note that adding and removing changes to any routes the changes are instantly visible but the components stay the same.
This issue got quite annoying after some time and I tried finding the fix in TailwindCSS and in the svelte.config.js (Not a .cjs file in Svelte-Kit) file.
After searching for a ton of answers I could not find anything that worked.
This behaviour is quite weird since in the other projects that I work on that use this same architecture of TailwindCSS and Svelte-kit the HMR works like a charm.
Here is the code for my Header.svelte file and the __layout.svelte
Header.svelte
<script>
</script>
<header>
<!-- TEST HEADER -->
<nav>
<ul class="flex gap-5 bg-red-500">
<!--These classes are tests and won't change the appearance of the Header unless I restart the script-->
<li>Home</li>
<li>About</li>
<li>Contact</li>
<!--Other random change that won't update-->
<li>Random Change</li>
</ul>
</nav>
</header>
__layout.svelte
<script>
import '../css/tailwind.css';
import Header from '../components/common/Header.svelte';
</script>
<Header />
<slot />
also my config files:
tailwind.config.cjs
module.exports = {
content: ['./src/**/*.svelte', './src/app.html'],
plugins: []
};
svelte.config.js
import preprocess from 'svelte-preprocess';
import path from 'path';
// #type {import('#sveltejs/kit').Config
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),
kit: {
vite: {
resolve: {
alias: {
'#components': path.resolve('./src/components'),
'#routes': path.resolve('./src/routes'),
'#utils': path.resolve('./src/utils'),
'#data': path.resolve('./src/data')
}
}
}
}
};
export default config;

This is how I solved the problem in my case:
I double checked and saw that I used a lowercase letter instead of a uppercase letter in the import path of my component. The component was strangely still working but the hot module reloading (HMR) was not working. I might have renamed a parent folder with an uppercase while developing, it might be the cause.
I stopped the terminal, ran 'npm run dev' or 'yarn dev' again
I set the component outside the layout file to check if HMR was working. It worked fine. Then put it back in the layout file, and it worked again.
Not really a satisfactory answer as I could not pinpoint the cause of the problem but anyone could try these steps if it happens for them. It might just solve it.

Related

import Css file from directory to inject in iframe head tag like <style> Vite + React JS

welcome to my ***** problem
I am spending some days trying to resolving something.
I am trying to create a webpage editor with Grapes JS, React JS and Vite everything was wonderful until the kingdom of creating different themes appears...
The themes are in different plugins, this plugins are in the project running from the react app, my problem is when i try to load a css file in the directory of the plugin :
import styles from "../../dist/main.css";
const cssStyle = document.createElement("style");
cssStyle.innerHTML = styles ;
const doc = iframe.contentDocument;
const f = setInterval(() => {
if (doc.readyState === "complete") {
doc.head.appendChild(cssStyle);
clearInterval(f);
}
}, 100);
This styles are apply globally in my react app and i only want to inject in a iframe, in the head tag.
Is any way to load a css file in react without compile globally this css file?
Thanks by the help
Vite automatically injects CSS styles into the page when you import a .css file. Quite helpful... until it's not. From what you describe I'm betting that is the culprit.
There is a way to disable that behavior: it looks like adding ?inline to the filename will disable the injection and just grab the file contents. So your first line would look like this:
import styles from "../../dist/main.css?inline";
That should give you styles as a pure string, and the rest of your code should then work.
P.S. Welcome to StackExchange :)

Bootstrap-vue - colors and fonts difference between local and production server

I'm tinkering with a node.js + Vue 2 + Bootstrap-Vue backend/admin tool on a local Debian Linux machine (running under WSL, but that shouldn't matter I think). It's an 'add-on' to an existing git repository Vue project that contains client-facing pages.
I build it/webpack it, zip it, and scp it to a test server which is pure Debian, running Node.js. Only thing that is notably different between the rest of the Vue web app and this 'added' Admin.vue page is that I added bootstrap and bootstrap-vue via the main.js file so that it's available everywhere in case I want to re-vamp the rest of the site to use bootstrap-vue at a later date:
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
// Import Bootstrap an BootstrapVue CSS files (order is important)
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
// Make BootstrapVue available throughout your project
Vue.use(BootstrapVue)
// Optionally install the BootstrapVue icon components plugin
Vue.use(IconsPlugin)
On my local machine I see:
but on the test server, that same page looks different. Different fonts, different tab colors at the top, different line spacing, form placeholder text is bold:
All I do is unpack the zip that was copied over. Because there is a node-express module serving up the pages to whoever asks, the new html/bootstrap/vue code gets reloaded when I update it.
A little sleuthing with the WhatFont extension for Chrome shows different fonts being used (first image is from my localhost run of the app on my desktop via Chrome, second image is from the remote test server, also seen from my desktop via Chrome):
The page behaves the same in Edge and Firefox. Switch from localhost to server - BAM! different view(vue?).
It's perplexing in the sense that I left everything as 'default' in Bootstrap - which appears to use the SegoeUI font as a default font. But once the code is uploaded to the server, it acts as if the font is missing. I know I don't have the SegoeUI font on my developer desktop, so I assume it's in with the Bootstrap modules, "compiled" in with the app.js and chunk.js files that get served up. When I grep search the built code, I do see 'SegoeUI' buried in the obfuscated code.
Rest of the app is untouched - no Bootstrap spread there (yet). Uses the Monserrat Font primarily, with Arial as fallback.
Any ideas are appreciated. Or point me someplace that I can dig around to see if there is some 'development' versus 'production' flag set (I haven't found one yet) that might change the behavior. If anyone has run across this issue before, please enlighten me! Thanks in advance. More details on request.
You need to manually include your desired font in public/index.html
// index.html
<head>
<!-- ... -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700">
<!-- ... -->
</head>
And in style define the connected font.
You can define it in any file, depending on your structure.
// example in App.vue
<template>
<!-- ... -->
</template>
<script>
export default {
<!-- ... -->
}
</script>
<style>
body {
font-family: Open Sans, sans-serif;
}
</style>
You can also download and locally connect fonts
Why do you see this behavior? Obviously, the library(bootstrap) uses the default fonts (those that are in the system), and if one of them is not available, the next one is used. I have not seen confirmation that he is downloading it locally or publicly.

Prevent vuetify from polluting global style scope

I am trying to essentially embed a Vue component into another one from a remote source (npm), without using a Vue Plugin. The components are mounting as expected, however, because the embedded component uses Vuetify, it's style is polluting the style of the "parent" application Here's some images that hopefully illustrate what i mean:
Note the primary colors of the root application before mounting the embedded component
Upon mounting of the Login (embedded) component:
I tried the strategy mentioned here, using less in the embedded component to import the vuetify css at a block level, but it doesn't seem to be working for me.
I realize that, in the end, I could ultimately solve this by ensuring the embedded theme matches the root applications theme, but I'd rather not have to rely on that. If my component is being built with webpack, why am I unable to apply Vuetify's css to just that component? Any suggestions?
happy to include code if necessary
To use with vue.js install postcss-parent-selector
npm i postcss-parent-selector -D
then create a postcss.config.js file in root and add following code
module.exports = {
plugins: [
require("postcss-parent-selector")({
selector: ".mywrapperclass",
}),
],
};
Then in public/index.html add a wrapper element around the app:
<div class="mywrapperclass">
<div id="app"></div>
</div>
Some links:
https://vue-loader-v14.vuejs.org/en/features/postcss.html
https://www.npmjs.com/package/postcss-parent-selector
https://github.com/postcss/postcss
I am currently having the same issue with my application. The possible solutions I've came up with are:
-Embedding the child Vue application via iframe and using a library like vuex-iframe-sync to pass props between Vuetify root app and the child app.
-Disabling Vuetify theme alltogether and perhaps customize components on my own:
// src/plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
const vuetify = new Vuetify({
theme: { disable: true },
})
-Another option was using webpack config to run a PostCSS plugin and possibly add prefixes to Vuetify's global styles while bundling the app, but I couldn't figure out how.
Please let me know if you make any progress on this topic!

How to install Semantic ui for Next.js

I have one problem here and cant solve it. I want to install Semantic ui on Next.js application via npm but it's impossible please help me.
if u have some ideas please help me
npm install semantic-ui
I tried this one but nothing changes.
I use semantic-ui-react in my next.js project and I like to use my own theme. Follow the instructions below to get going.
First and foremost run npm install --save-dev semantic-ui. Soon you will see an interactive prompt. Answer questions presented the following way.
Set-up Semantic UI - Choose ‘Express (Set components and output folder)’
We detected you are using NPM Nice! Is this your project folder? - Choose ‘Yes’
Where should we put Semantic UI inside your project? Hit return (This will put a directory named ‘semantic’ in root)
What components should we include in the package? This is upto you. Check the ones you need and uncheck the ones you don’t.
Should we set permissions on outputted files? Choose ‘No’
Do you use a RTL (Right-To-Left) language? Pick your favourite option
Where should we output Semantic UI? Write a custom path in your terminal ../static/semantic/dist
Now we are going to need gulp to run compilation tasks to build your theme.css under dist/ directory that you will use in your project.
Run yarn add --dev gulp
and add the following to your package.json under “scripts” like this
{
"dependencies": {
"next": "^7.0.2",
"react": "^16.6.3",
"react-dom": "^16.6.3"
},
"scripts": {
"dev": "next",
"build-semantic": "cd semantic && gulp build-css build-assets”,
"watch-semantic": "cd semantic && yarn run build-semantic && gulp watch"
},
"devDependencies": {
"semantic-ui": "^2.4.2"
}
}
Now if you run yarn watch-semantic, gulp will compile source files and create a dist/ under semantic/. Under dist/ you will see semantic.min.css
We are just about done. Now you have to include this .css in page/component that is shared by all pages or components. Fortunately, next.js has a solution.
_document.js (https://nextjs.org/docs/#custom-document)
Create _document.js under pages/ and include your recently created semantic.min.css like below.
import Document, { Head, Main, NextScript } from 'next/document'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<html>
<Head>
<link
href="/static/semantic/dist/semantic.min.css"
rel="stylesheet"
/>
</Head>
<body className="custom_class">
<Main />
<NextScript />
</body>
</html>
)
}
}
If you want to do the following in _app.js:
import 'semantic-ui-css/semantic.min.css'
You will need: https://github.com/zeit/next-plugins/tree/master/packages/next-css.
Then, you can follow the advice I found here: https://github.com/zeit/next-plugins/issues/432.
Specifically, see antonioOrtiz 24 Mar comment.
There's a nice starter project that uses Next.js + Fomantic-UI + Styled Components.
https://github.com/skydiver/nextjs-semantic
For Semantic-UI version, check out v1.1.0 branch.
https://github.com/skydiver/nextjs-semantic/tree/v1.1.0
Another alternative I haven't seen mentioned in the comments yet:
Create a layout wrapper around your pages and import there the library CSS from the CDN.
import Head from 'next/head';
const Layout = () => (
<>
<Head>
<link href="https://cdn.jsdelivr.net/npm/semantic-ui#2.4.2/dist/semantic.min.css" rel="stylesheet" />
</Head>
{children}
</>
);
export default Layout;
And in your pages:
import Layout from '#components/Layout';
const AboutPage = () => (
<Layout>
<article>
I am the about page
</article>
</Layout>
);
export default AboutPage;
It will allows to do some quick tests without having to install any additional packages.

React-router not loading css for nested pages on refresh

I'm trying to setup a react-router for my first React webapp, it seems to be working except that the css doesn't load for my nested pages when I refresh the pages.
However it works for just one level e.g /dashboard but the css won't load for /components/timer
Here is what my index.jsx file looks like
import './assets/plugins/morris/morris.css';
import './assets/css/bootstrap.min.css';
import './assets/css/core.css';
import './assets/css/components.css';
import './assets/css/icons.css';
import './assets/css/pages.css';
import './assets/css/menu.css';
import './assets/css/responsive.css';
render(
<Router history={browserHistory}>
<Route path="/" component={Dashboard}/>
<Route path="/components/:name" component={WidgetComponent}/>
<Route path="*" component={Dashboard}/>
</Router>,
document.getElementById('root')
);
Any idea why?
I had this problem too, where my app wasn't loading style sheets and the like. However, I was importing my assets directly into my index.html entry point.
By replacing the links with absolute paths as per this documentation, my problem was resolved.
For me, this meant changing
<head>
<link rel="stylesheet" href="./style.css" ></link>
</head>
to this:
<head>
<link rel="stylesheet" href="/style.css" ></link>
</head>
I'm not sure if the same thing would work for your import statements, but it is worth a shot.
FYI I'm using the project layout from create-react-app.
Found it!
Add the HTML Element:
<base href="/" /> <!-- for local host -->
to your index page to set a base case for your URL so all else will follow suite.
I added
<base href="/" /> <!-- for local host -->
to my index.html head
And it is resolved.
The simplest solution is here (Need to change index.html only)
Just use %PUBLIC_URL% before every CSS or JS file.
You can check an example of %PUBLIC_URL% in index.html file if you created react app through create-react-app.
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
One thing is must: your CSS files and js files should be under a public directory.
If you are using create-react-app workflow, put the assets under public folder and use the special variable PUBLIC_URL.
Inside index.html use %PUBLIC_URL%:
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
Inside JS/JSX files use process.env.PUBLIC_URL:
render() {
// Note: this is an escape hatch and should be used sparingly!
// Normally we recommend using import for getting asset URLs
// as described in “Adding Images and Fonts” above this section.
return <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;
}
Recommended Approach:
import stylesheets, images, and fonts from JavaScript by placing it along with src files.
import React from 'react';
import logo from './logo.png'; // Tell Webpack this JS file uses this image
console.log(logo); // /logo.84287d09.png
function Header() {
// Import result is the URL of your image
return <img src={logo} alt="Logo" />;
}
export default Header;
Adding assets to public folder
When to use public folder
I know its a bit old thread, but ill share my solution here. Its a solution for setup that uses webpack instead create-react-app.
I found every other solution suggests to change the <link path in the html file. But like in my case webpack handles the asset linking.
I faced the same problem today. Routes like /some_route works but - /some_route/second_level it doesn't, leaving behind a message in console stating -
Refused to apply style from 'http://localhost:8080/some_route/some_style.css'.
I fixed this problem by updating my webpack.config.js file
output: {
filename: 'build.js',
path: path.join(__dirname, '/dist'),
publicPath: '/', ////// <-- By adding this line
}
Hope it helps someone. Thanks!
Your script is not loading your css due to the 404 errors. Your webserver is not redirecting all /components/* request to index file and then routing to your view via react.
But now, specifically about fixing your css issues... In the past, I've struggled with the css imports in jsx files, so you are not alone :) Instead, I've chosen to use SASS or LESS to compile my css to a bundle.css file with grunt or gulp. Then load that bundle.css directly on my index.html file. One neat trick about using css compilers is every time you change a .scss or .less file, your bundle.css will get updated.
Hope I pointed you in the right direction.
Cheers,
I know this is weird , but if you use history#5.0.0 ,delete it and install history#4.10.1
react-router have many incompatibilities with history version 5 .
for me it's worked.

Resources