Trouble adding Bootstrap 4 CSS with Webpack 4 in ReactJS SpringBoot Application - css

I am getting an error where webpack is not able to resolve the bootstrap 4 css which is sitting in the node_modules directory. I have looked at a number of tutorials around webpack 4 and bootstrap 4 but I am thinking it is not in the same folder structure.
I've also tried changing the import bootstrap css trying to change the directory to push it to the node_modules directory but that does not seem to work.
Error log from Spring Tool Suite
[INFO] ERROR in ./src/main/resources/static/js/app.js
[INFO] Module not found: Error: Can't resolve 'bootstrap/dist/css/boostrap.min.css' in 'C:\sourcecode\personal-website\src\main\resources\static\js'
[INFO] # ./src/main/resources/static/js/app.js 26:0-46
webpack.config.js
var path = require('path');
module.exports = {
entry: './src/main/resources/static/js/app.js',
performance: {
hints: false
},
output: {
path: __dirname,
filename: './src/main/resources/static/built/bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: ['#babel/react', '#babel/env']
}
},
{
test: /\.css$/,
include: /stylesheets|node_modules/,
use: [ "style-loader", "css-loader" ]
}
]
}
};
app.js
import 'bootstrap';
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/boostrap.min.css';
import Landing from './components/Landing';
class App extends React.Component {
render() {
return (
<div className="container">
<Landing />
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('react-app')
);

I'm not sure what your folder structure is like. But, I believe everything is relative to the location of the file where you're importing bootstrap's css from.
Given the folder structure below
sourceCode
|--node_modules
|--bootstrap
|--dist
|--css
|--bootstrap.min.css
|--routes
|--src
|--main
|--resources
|--static
|--app.js
|--dist
|--views
if you're importing bootstrap's CSS stylesheet in the app.js script, it would go like:
import '../../../../node_modules/bootstrap/dist/css/bootstrap-min.css';
The double period (..) means you're moving one step up the folder structure/tree.
You did say you've tried changing your import. But, I based my answer on what you've shown.
On the other hand, try taking a look at VS Code then check out the Path Intellisense extension. It'll help you with those imports. Happy coding :)

Related

Configuring Vanilla TS Vite project to keep CSS files separated

I am trying to set up a basic (css) library with vanilla TS and Vite 4.
I want to have a main js and css file at the top level so you can import the whole thing in one go. I also want to have component level imports where you can chose to just import the components js + css. The combined css and JS files are working fine; and the individual component JS file is working fine too.
Currently I'm running into the problem where I can't seem to keep an isolated version of the CSS files next to the JS files after bundling. My build is currently creating :
I've gone over the docs of both Vite and Rollup but I can't seem to figure out how to do the same to my CSS as I'm doing to my JS.
dist
--components
----button
------button.js
--main.css
--main.js
My preferred output would be:
dist
--components
----button
------button.js
------button.css
--main.css
--main.js
In my `main.ts` I'm importing:
import './style.scss'
import './tokens.scss'
import './components/button/button.scss'
vite.config.js
import { defineConfig } from 'vite'
import { resolve } from 'path'
export default defineConfig({
build: {
cssCodeSplit: false,
manifest: true,
rollupOptions: {
output: {
assetFileNames: () => 'main[extname]',
}
},
lib: {
formats: ['es'],
entry: {
main: resolve(__dirname, 'src/main.ts'),
button: resolve(__dirname, 'src/components/button/button.ts')
},
name: 'CSSFramework',
fileName: (_, fileName) => fileName === 'main' ? '[name].js' : 'components/[name]/[name].js',
},
},
});
Thanks in advance !

React component library, how to correctly bundle fonts with rollup

I'm working on a project which has a React component library, and a Next JS app which imports said library. I've read a lot of questions on SO and attempted most of the solutions to no avail.
We have the component library working, fonts and all, and in storybook looks great
There's two fonts we import in our package.json (in devDependencies)
"#fontsource/inter": "4.5.12",
"#fontsource/material-icons": "4.5.4",
The material-icons font is imported in our <Icon /> component
import "#fontsource/material-icons";
And referenced in the tailwind config
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx,mdx}"],
theme: {
fontFamily: {
sans: ["Inter", "ui-sans-serif", "sans-serif"],
heading: ["Inter", "ui-sans-serif", "sans-serif"],
},
This works in storybook with no problems
But when imported into the Next JS app and the same component used
The files seem to be available in the node_modules folder of the Next JS app
Here is the roll up config:
import resolve from "#rollup/plugin-node-resolve";
import commonjs from "#rollup/plugin-commonjs";
import typescript from "rollup-plugin-typescript2";
import postcss from "rollup-plugin-postcss";
import dts from "rollup-plugin-dts";
import json from "#rollup/plugin-json";
import pkg from "./package.json";
export default [
{
input: "src/index.ts",
output: [
{
file: pkg.main,
format: "cjs",
sourcemap: true,
},
{
file: pkg.module,
format: "esm",
sourcemap: true,
},
],
plugins: [
resolve(),
commonjs(),
typescript({ tsconfig: "./tsconfig.json" }),
postcss(),
json(),
],
external: [
"react",
"react-dom",
"#fontsource/inter/400.css",
"#fontsource/inter/600.css",
"#fontsource/inter/700.css",
"#fontsource/material-icons",
"react-loading-skeleton/dist/skeleton.css",
],
},
{
input: "dist/types/index.d.ts",
output: [{ file: "dist/index.d.ts", format: "esm" }],
plugins: [dts()],
external: [
"react",
"react-dom",
"#fontsource/inter/400.css",
"#fontsource/inter/600.css",
"#fontsource/inter/700.css",
"#fontsource/material-icons",
"react-loading-skeleton/dist/skeleton.css",
],
},
];
QUESTION: what I'd ideally like to do is export all the referenced css from the component library, such that in the next app's _app.tsx I can use
import "#us/component-library/styles.css";
How do I configure rollup to bundle the referenced css and expose it in the build folder?
Also: if there is an alternative or better way of doing this, we aren't precious over the plugins used and would be open to being shown a better (or correct) way of doing this.
Appreciate any help!
If anyone is still in the same boat - here's how I solved it in the end...
New rollup.config.js
import resolve from "#rollup/plugin-node-resolve";
import commonjs from "#rollup/plugin-commonjs";
import typescript from "rollup-plugin-typescript2";
import postcss from "rollup-plugin-postcss";
import dts from "rollup-plugin-dts";
import json from "#rollup/plugin-json";
import pkg from "./package.json";
import copy from "rollup-plugin-copy";
export default [
{
input: "src/index.ts",
output: [
{
file: pkg.main,
format: "cjs",
sourcemap: true,
},
{
file: pkg.module,
format: "esm",
sourcemap: true,
},
],
plugins: [
postcss(),
resolve(),
commonjs(),
typescript({ tsconfig: "./tsconfig.json" }),
json(),
copy({
targets: [
{
src: "node_modules/#fontsource/inter/files/*",
dest: "./dist/files",
},
{
src: "node_modules/#fontsource/material-icons/files/*",
dest: "./dist/files",
},
],
}),
],
external: ["react", "react-dom"],
},
{
input: "dist/types/index.d.ts",
output: [{ file: "dist/index.d.ts", format: "esm" }],
plugins: [dts()],
external: ["react", "react-dom"],
},
];
Then in src/theme/input.css
#import url("../../node_modules/#fontsource/inter/400.css");
#import url("../../node_modules/#fontsource/inter/600.css");
#import url("../../node_modules/#fontsource/inter/700.css");
#import url("../../node_modules/#fontsource/material-icons/index.css");
#import url("../../node_modules/react-loading-skeleton/dist/skeleton.css");
#tailwind base;
#tailwind components;
#tailwind utilities;
...
foo {
bar...
Then in our consuming Next app, I no longer have to have the #fontsource/font import in the package.json.
In my head, this works because the rollup build, using rollup-plugin-postcss, leverages the css imports and bundles everything together as part of the css, rather than trying to re-package imports or manage external dependencies from the consuming app.
Pretty sure my rollup config can still be trimmed down, in particular where I'm using rollup-plugin-copy to copy the #fontsource/font files. But for now this is working and means our consuming apps don't need to care about importing fonts.
However, this has is drawbacks as I'm not sure how this would work if we wanted to override the font.
Perhaps re-defining the inter font in the calling app? And then assigning something else to it?
Or maybe overriding the fontFamily in our tailwind config? Not sure yet. Will update when I have a better answer.
Hope this helps someone else - when I get more time to spend on trimming the rollup config I'll post the latest.
Kia Ora!

Storybook LESS imports included globally. How to separate styles per story?

On my storybook site, I have added Less imports to some of my components, but the CSS files generated by webpack are included globally in the of the site for all components. From the storybook documentation, it seems like CSS should be isolated to each component by default, so I'm not sure what the issue is. Any suggestions on how to isolate styles per component/story?
Ver: Storybook 6.2.9
Main.js (less-loader):
config.module.rules.push({
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
lessOptions: {
paths: [path.resolve(__dirname, "node_modules")],
},
sourceMap: true,
webpackImporter: false,
}
}]
});
stories/component.stories.js:
import React from 'react';
import { Component } from './component.js';
import './component.less';
import '#package/index.less';
...
stories/component-2.stories.js:
import React from 'react';
import { Component2 } from './component2.js';
import './component2.less';
import '#package-2/index.less';
...
This results in all LESS files being converted to CSS and added to the section of the site. They do not load separately per story.
If I missed any info, please lmk. Thanks :)

Importing css file to specific component react app

I am trying to import css to my specific component of react app.
webpack config:
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
use: 'css-loader',
}),
}
but css is not applied.
I also included the main css inside index.html. Is it the reason why I cannot apply another css file?
<link rel="stylesheet" href="../style/style.css">
Can you suggest me what's missing?
It depends on the webpack version you're using. For example, if you're using Webpack 4, then your development config would be:
{
test: /\.s?css$/, // test for scss or css files
use: [
'style-loader', // try to use style-loader or...
{
loader: 'css-loader', // try to use css-loader
options: {
sourceMap: true, // allow source maps (allows css debugging)
modules: true, // allow css module imports
camelCase: true, // allow camel case imports
localIdentName: '[local]___[hash:base64:5]', // set imported classNames with a original className and a hashed string in the DOM, for example: "exampleClassName__2fMQK"
},
},
],
}
example.css (must use camel case instead of snake case)
.exampleClassName {
text-align: center;
}
example.js
import React from 'react';
import { exampleClassName } from './example.css';
export default () => (
<h1 className={exampleClassName}>I am centered!</h1>
)
For production, you'll want to use OptimizeCSSAssetsPlugin and MiniCssExtractPlugin :
minimizer: [
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
map: {
inline: false,
annotation: true
}
}
}),
],
{
plugins: [
new MiniCssExtractPlugin({
filename: `css/[name].[contenthash:8].css`,
chunkFilename: `[id].[contenthash:8].css`,
}),
]
}
When you run webpack to build your application for production, it'll compile the css and (when the webpack config is set up properly) will generate an index.html that automatically adds a link to the compiled stylesheet.
Webpack is a steep learning curve and there's a lot of missing options from the above examples, so if you're just trying to get it up and running, then I have a Webpack-React-Boilerplate that has (s)css modules imports and a lot more already configured for you. I've included notes within the webpack config files to help assist as to what each option is doing.
Otherwise, if you're trying to learn older versions of webpack, then you can eject the create-react-app and reverse engineer/look at their extensive webpack notes.

Unable to style react component using webpack

So I am trying to add some css style to my react components but failed.
My webpack.config.js looks like:
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, './build');
var APP_DIR = path.resolve(__dirname, './src/client');
const config = {
entry: {
main: APP_DIR + '/index.js'
},
output: {
filename: 'bundle.js',
path: BUILD_DIR,
},
module: {
rules: [
{
test: /\.css$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader?modules=true&camelCase=true"
}]
},
{
test: /\.(jsx|js)?$/,
use: [{
loader: "babel-loader",
options: {
cacheDirectory: true,
presets: ['#babel/preset-react']
}
}]
}
],
}
};
module.exports = config;
My client code folder looks like:
Client
--style
----index.css
--index.js
index.css looks like:
body{
color: #555;
background: #f85032;
margin: 10px 30px;
}
Inside index.js, I am loading the css file using
import css from './style/index.css';
Then I do:
npx webpack
npm start
There's no error message in console output. The webpage shows up but there's no css style. Can someone please help me with this? Thanks!
It appears that if I do some inline css in index.html then it works? Any suggestion why this happens? Thanks!
Change to import './style/index.css'; and see if that works
I am just guessing here, since i can not see your index.js
From your webpack file i can see that you are using css modules.
This means that you can not just assign classes as you would usually do it, but you must get them from the css you imported.
Hence
'<div className="className">'
Becomes
'<div class=Name"' + css.className + '">'
The reason is thay css modules is doing some clever naming to always make the imported css unique to ensure you are not having any global scoping and conflicts (which is what you want with css modules)
UPDATE
I have tried to create a local setup with your webpack config. You can download it here (It is just a zip file).
Unzip and enter folder then run npm install and npm run webpack. You can now open build/index.html and see the result.
Maybe then you can see what you are doing differently?

Resources