Unable to import css files into NextJs project - javascript

Currently I have my index.js file that has my display components. For CSS I have downloaded a css file from an external source. I am then adding the .css file into my styles folder that comes when you make the initial npx create-next-app. This file I'm then trying to import into my index.js file like so: import bootStyles from "../styles/bootstrap.css". But doing this gives me this error:
error - ./styles/bootstrap.css Global CSS cannot be imported from
files other than your Custom . Please move all global CSS imports
to pages_app.js. Or convert the import to Component-Level CSS (CSS
Modules). Read more: https://nextjs.org/docs/messages/css-global
Location: pages\index.js
Additionally I have also tried using the Head component like so:
import Head from 'next/head'
<Head>
<title>Create Next App</title>
<link rel="stylesheet" href="../styles/bootstrap.css"/>
</Head>
This doesnt show an error but the styles still dont reflect on my webpage.

Either put all your CSS imports in _app.tsx or you can add *.module.css to your filenames so they get picked up.
You can also override the nextjs webpack config:
// next.config.js
module.exports = {
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
return config
},
}
...
{
test: /\.s?[ac]ss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
exclude: [/node_modules/],
},
In order to override the module rules and css loader, however I wouldn't recommend this if you don't know what you're doing.

Related

Unable to change the publicPath in Vue 3 with Vite.js

I am trying to change the public path for production build but can't seem to get it to work. When I build for production, I would like to change the public path from / to ./ but I could not find anything in the documentation how to do this. I am using vite.js as my build tool. Maybe this is something Vue 3 and Vite specific, I'm not sure.
I have tried adding a vue.config.js file and also .env variables but so far nothing is working.
When I build, I get this output with path starting with /:
<head>
<script src="/assets/index.30c61b3b.js"></script>
<link href="/assets/vendor.29497e16.js">
<link href="/assets/index.7123a98f.css">
</head>
But for production I would like it to change to ./ like this:
<head>
<script src="./assets/index.30c61b3b.js"></script>
<link href="./assets/vendor.29497e16.js">
<link href="./assets/index.7123a98f.css">
</head>
I tried adding vue.config.js but it is not helping:
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? './' : '/'
}
and also .env
NODE_ENV=production
BASE_URL=./
I found the answer, I needed to add a base option to vite.config.js like this:
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue({
reactivityTransform: true
})
],
base: './',
})
https://vitejs.dev/config/#base

Loading SVGs within .scss with Webpack and svgr loader

Webpack config:
For a .svg I use config:{ test: /\.svg$/, use: ['svgr/webpack'] }
For .scss I use css-loader, postcss-loader and sass-loader
Folder structure:
I have folder structure that looks like this:
- App
-- styles
--- globals.scss // Here I import my partials
--- partials
---- _my_partial.scss
-- icons
--- svgs
---- my_icon.svg
svgr loader:
I like svgr loader as it allows me to just import my icon and use it as React component:
import MyIcon from './icons/svgs/my_icon.svg';
...
<MyIcon />
The actual problem:
I was fine with this approach but I have to get one of the svgs as a background-image, so inside _my_partial.scss I wrote:
background-image: url(../icons/svgs/my_icon.svg);
I am up just one folder in this url as when being up two, it complained that it cannot resolve it - I guess this is because I import my partials in my globals.scss.
With this setup all I get in the browser is:
GET http://localhost:3005/[object%20Module] 404 (Not Found)
svgr/webpack turns your svg into react components, so when using svg into scss it's actually an object / react component. Change svgr/webpack to file-loader in order to use that. If you want to still use both, you could try something like:
{ test: /\.react.svg$/, use: ['svgr/webpack'] }
{ test: /\.svg$/, use: ['file-loader'] }
then rename all the svg's that you want as React components to filename.react.svg and the rest just leave with .svg.
I haven't tested this though :)
UPDATE: Looking at the documentation (section: Handle SVG in CSS, Sass or Less), it seems you can use svgr/webpack with file-loader:
https://github.com/smooth-code/svgr/tree/master/packages/webpack
{
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
issuer: {
test: /\.jsx?$/
},
use: ['babel-loader', '#svgr/webpack', 'url-loader']
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url-loader'
},
}
Either way, you probably need to make a few changes to fit in your needs but it supports it :)

How to bundle vendor CSS files into a React app with Webpack?

I have some 3rd party libs, like Mapbox GL, which are installed via npm and have some CSS files they rely on in their work.
As for Mapbox GL, there is mapbox-gl/dist/mapbox-gl.css in node_modules. I have index.html which is used as the entry point for my React app and contains a link to a CSS file with some defaults.
<link rel="stylesheet" href="/vendor/core.css">
All other CSS rules are provided by CSS modules, so I have a single CSS file in a React UI component folder and import it from the component like this:
import * as style from './MyComponent.css';
How do I import vendor CSS files, like Mapbox GL example above and make the rules from it apply to the app?
If your vendor css files are specific to a component, you can import them directly into your component, like this:
// Component1.js
import React from 'react';
...
import 'vendor/path/to/styles.css';
...
If you want to import a general css file (such as normalize.css), you can import them into your top-level html view. I usually have a JSX file which is transpiled by webpack to index.html. So you can do this:
// index.jsx (transpiled to index.html)
<style
dangerouslySetInnerHTML={{
__html: require('!css-loader!normalize.css/normalize.css'),
}}
/>
Or, if you have pure HTML, you can let webpack do it for you using the html-loader
For your reference, this is my webpack.config:
webpackConfig = {
module: {
rules = [
{
// excluding for node-modules
test: /.css$/,
exclude: path.resolve('./node_modules'),
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
camelCase: true,
importLoaders: 1,
localIdentName: '[path][name]__[local]--[hash:base64:5]',
},
},
'postcss-custom-loader',
],
},
{
// only for node-modules
test: /.css$/,
include: path.resolve('./node_modules'),
use: ['style-loader', 'css-loader', 'postcss-custom-loader'],
},
...
}

How to import a CSS file in a React Component

I want to import a CSS file into a react component.
I've tried import disabledLink from "../../../public/styles/disabledLink"; but I get the error below;
Module not found: Error: Cannot resolve 'file' or 'directory' ../../../public/styles/disabledLink in c:\Users\User\Documents\pizza-app\client\src\components # ./client/src/components/ShoppingCartLink.js 19:20-66 Hash: 2d281bb98fe0a961f7c4 Version: webpack 1.13.2
C:\Users\User\Documents\pizza-app\client\public\styles\disabledLink.css is the location of the CSS file I'm trying to load.
To me it seems like import is not looking up the correct path.
I thought with ../../../ it would start to look up the path three folder layers above.
C:\Users\User\Documents\pizza-app\client\src\components\ShoppingCartLink.js is the location of the file that should import the CSS file.
What am I doing wrong and how can I fix it?
You don't even have to name it if you don't need to:
e.g.
import React from 'react';
import './App.css';
see a complete example here (Build a JSX Live Compiler as a React Component).
You need to use css-loader when creating bundle with webpack.
Install it:
npm install css-loader --save-dev
And add it to loaders in your webpack configs:
module.exports = {
module: {
loaders: [
{ test: /\.css$/, loader: "style-loader!css-loader" },
// ...
]
}
};
After this, you will be able to include css files in js.
I would suggest using CSS Modules:
React
import React from 'react';
import styles from './table.css';
export default class Table extends React.Component {
render () {
return <div className={styles.table}>
<div className={styles.row}>
<div className={styles.cell}>A0</div>
<div className={styles.cell}>B0</div>
</div>
</div>;
}
}
Rendering the Component:
<div class="table__table___32osj">
<div class="table__row___2w27N">
<div class="table__cell___2w27N">A0</div>
<div class="table__cell___1oVw5">B0</div>
</div>
</div>
The following imports an external CSS file in a React component and outputs the CSS rules in the <head /> of the website.
Install Style Loader and CSS Loader:
npm install --save-dev style-loader
npm install --save-dev css-loader
In webpack.config.js:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
}
}
In a component file:
import './path/to/file.css';
CSS Modules let you use the same CSS class name in different files without worrying about naming clashes.
Button.module.css
.error {
background-color: red;
}
another-stylesheet.css
.error {
color: red;
}
Button.js
import React, { Component } from 'react';
import styles from './Button.module.css'; // Import css modules stylesheet as styles
import './another-stylesheet.css'; // Import regular stylesheet
class Button extends Component {
render() {
// reference as a js object
return <button className={styles.error}>Error Button</button>;
}
}
The solutions above are completely changed and deprecated. If you want to use CSS modules (assuming you imported css-loaders) and I have been trying to find an answer for this for such a long time and finally did. The default webpack loader is quite different in the new version.
In your webpack, you need to find a part starting with cssRegex and replace it with this;
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash:base64:5]'
}),
}
You can import css file if css file reside in a same folder where you want to import than just simple try this
import './styles.css'
if css file is far away from our component that navigate that place where file is reside and use this like
import '../mainstyles/styles.css'
In cases where you just want to inject some styles from a stylesheet into a component without bundling in the whole stylesheet I recommend https://github.com/glortho/styled-import. For example:
const btnStyle = styledImport.react('../App.css', '.button')
// btnStyle is now { color: 'blue' } or whatever other rules you have in `.button`.
NOTE: I am the author of this lib, and I built it for cases where mass imports of styles and CSS modules are not the best or most viable solution.
You can also use the required module.
require('./componentName.css');
const React = require('react');
Install Style Loader and CSS Loader:
npm install --save-dev style-loader
npm install --save-dev css-loader
Configure webpack
module: {
loaders: [
{
test: /\.css$/,
loader: 'style-loader'
}, {
test: /\.css$/,
loader: 'css-loader',
query: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
}
]
}
Using extract-css-chunks-webpack-plugin and css-loader loader work for me, see below:
webpack.config.js Import extract-css-chunks-webpack-plugin
const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
webpack.config.js Add the css rule,
Extract css Chunks first then the css loader css-loader will embed them into
the html document, ensure css-loader and extract-css-chunks-webpack-plugin are in the package.json dev dependencies
rules: [
{
test: /\.css$/,
use: [
{
loader: ExtractCssChunks.loader,
},
'css-loader',
],
}
]
webpack.config.js Make instance of the plugin
plugins: [
new ExtractCssChunks({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css'
})
]
And now importing css is possible
And now in a tsx file like index.tsx i can use import like this
import './Tree.css' where Tree.css contains css rules like
body {
background: red;
}
My app is using typescript and this works for me, check my repo for the source :
https://github.com/nickjohngray/staticbackeditor
You can import your .css file in .jsx file
Here is an example -
import Content from '../content/content.jsx';

Webpack not loading SCSS with react-toolbox

I am trying to bootstrap a new react app and use the react-toolbox library and webpack. I am unable to get both react-toolbox's styles and my own app's styles to load.
The way I'm used to importing scss files is from the react files/views/components they go with, so they are located in the same folder. So if I have a react component file called header.js, in the same directory there is header.scss. Header.js calls import './header.scss'. In webpack, what I previously used to load scss was:
{
test: /\.s?css$/i,
loader: 'style!css!sass?' +
'includePaths[]=' + (path.resolve(__dirname, './node_modules')),
},
But when I include react-toolbox, this setup completely excludes react-toolbox's styles. I found this issue https://github.com/react-toolbox/react-toolbox/issues/121 where mattgi recommends this webpack-config:
{
test : /(\.scss|\.css)$/,
include : path.join(__dirname, '../../', 'src'),
loaders : [ 'style', 'css', 'sass' ]
},
{
test : /(\.scss|\.css)$/,
include : /(node_modules)\/react-toolbox/,
loaders : [
require.resolve('style-loader'),
require.resolve('css-loader') + '?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
require.resolve('sass-loader') + '?sourceMap',
]
},
This resolves the react-toolbox styles not loading, but then when I try to import my own scss files in a js file, webpack throws this error for the scss file: You may need an appropriate loader to handle this file type. (I have sass-loader installed).
In addition, if I include the scss file in the same directory with the same name (some-react-class.js and some-react-class.scss), the containing component of SomeReactClass that is importing some-react-class.js imports it as an object instead of a function which makes it seem like it is importing the scss instead of the js.
Help :(
Try to omit "include" property like this:
{
test: /(\.css|\.scss)$/,
loader: 'style!css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!sass?sourceMap'
}
This loader should include your *.scss and those from react-toolbox.
Seems hacky - but I did this to get it to work:
{
test: /\.s?css$/,
loaders: ['style', 'css', 'sass'],
exclude: /(node_modules)\/react-toolbox/
},
{
test : /(\.scss|\.css)$/,
include : /(node_modules)\/react-toolbox/,
loaders : [
require.resolve('style-loader'),
require.resolve('css-loader') + '?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
require.resolve('sass-loader') + '?sourceMap'
]
},
Bootstrap styles and react-toolbox styles work - but I'm having a hell of a time adding a file to override the default sass variables via toolbox-loader. Not sure if the issue is related to this hackiness...ugh headache

Categories

Resources