How to import css with webpack? - css

TWO PART QUESTION
My steps:
Created empty folder
opend cmd
navigate to folder and run npm init -f
run vue init webpack
run npm install
npm i bootstrap-vue
npm run dev
my main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
Vue.use(BootstrapVue);
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
webpack.base.conf.js:
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production' ?
config.build.assetsPublicPath : config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'#': resolve('src'),
}
},
module: {
rules: [{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{ //this rule will only be used for any vendors
test: /\.css$/,
loaders: ['style-loader', 'css-loader'],
include: [/node_modules/]
},
{
test: /\.css$/,
loaders: ['to-string-loader', 'css-loader'],
exclude: [/node_modules/] //add this line so we ignore css coming from node_modules
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
}
}
when I run this I get:
Module build failed: Unknown word (5:1)
Part 2:
After some time found a solution to the above problem by installing a loader package and changin my main.js to this:
import Vue from 'vue'
import App from './App'
import router from './router'
import '!style-loader!css-loader!bootstrap/dist/css/bootstrap.css';
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
this solved my first problem BUT:
If i try to add a local css file like so:
import Vue from 'vue'
import App from './App'
import router from './router'
import '!style-loader!css-loader!bootstrap/dist/css/bootstrap.css';
import './content/bootstrapGrid.css'
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})
I again get the same error:
Module build failed: Unknown word (5:1)
I am new to webpack, vue and the entire SPA.
Been at this for a while now and im stuck, anyone that can see what I am missing?

!css-loader
This is the plain css loader. It will return the css code interpreting the resources inside, but it will not add it to the page.
With this loader #import and url(...) are interpreted like require() and will be resolved.
!style-loader
This loader adds CSS to the DOM by injecting a or tag.
To inject a you need to get the content of the css file, and then inject that.
require("style!raw!./file.css");
// => add rules in file.css to document
But it’s recommended to combine it with the css-loader, as it will interpret all the resources in your css file, instead of just having the raw css. (Check)
require("style!css!./file.css");
// => add rules in file.css to document
If you want to add a to your css file, you need to first have the url to that file, for that you can use the file-loader.
require("style/url!file!./file.css");
// => add a <link rel="stylesheet"> to file.css to document
Hope this helps!
Refer: css-loader, style-loader
A good article on this here

Related

TailwindCSS 3.0 Upgrade overriding button styles

Problem:
Button class being overridden by default tailwind base classes. Not sure why my classes on the element aren't being applied.
Question:
How can I get my styles to apply properly?
Screenshot:
As you can see background color on .documentCategory__row is being overridden by button, [type=button] on index.scss which is being defined within #tailwind/base.
/* index.scss */
:root {
--color-primary: #00a3e0;
--color-secondary: #470a68;
--color-success: #87d500;
--color-accent: #e87722;
/* Dark themes below */
--color-dark-primary: rgba(31, 41, 55, 1);
--dark-text: rgba(187, 193, 198, 1);
}
#import "tailwindcss/base";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
I'm not sure if this has to do with me switching to dart-scss so here is my webpack configuration in case I am missing something
import path from 'path'
import { Configuration as WebpackConfiguration, HotModuleReplacementPlugin } from 'webpack'
import { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
import HtmlWebpackPlugin from 'html-webpack-plugin'
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'
import ESLintPlugin from 'eslint-webpack-plugin'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
const CopyPlugin = require('copy-webpack-plugin');
interface Configuration extends WebpackConfiguration {
devServer?: WebpackDevServerConfiguration;
}
const config: Configuration = {
mode: 'development',
devServer: {
static: path.join(__dirname, 'build'),
historyApiFallback: true,
port: 4000,
open: true,
hot: true,
},
output: {
publicPath: '/',
},
entry: './src/index.tsx',
module: {
rules: [
{
test: /\.(ts|js)x?$/i,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'#babel/preset-env',
'#babel/preset-react',
'#babel/preset-typescript',
],
},
},
},
{
test: /\.(sa|sc|c)ss$/i,
use: [
'style-loader',
'css-loader',
'sass-loader',
{
loader: 'postcss-loader', // postcss loader needed for tailwindcss
options: {
postcssOptions: {
ident: 'postcss',
plugins: [tailwindcss, autoprefixer],
},
},
},
],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
loader: 'file-loader',
options: {
outputPath: '../fonts',
},
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
}),
new HotModuleReplacementPlugin(),
new CopyPlugin({
patterns: [
// relative path is from src
{ from: 'public/images', to: 'images' },
],
}),
// Add type checking on dev run
new ForkTsCheckerWebpackPlugin({
async: false,
}),
// Add lint checking on dev run
new ESLintPlugin({
extensions: ['js', 'jsx', 'ts', 'tsx'],
}),
],
devtool: 'inline-source-map',
};
export default config
If there are other files I am missing that are needed let me know!
without seeing what your index.tsx looks like I can only make a guess, but here's what caused this issue in our app:
in our index.tsx we were importing index.css after importing our component tree with import App from 'src/App. thus the css was loaded into the site in the wrong order. imports from components first (css modules, normal css imports), tailwind last.
go to your entry file (probably index.tsx) and try moving your import 'index.scss' line above importing the root component.
like this for example
/* index.tsx */
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'; // this file holds all tailwind styles
import { App } from 'src/App';
// ...
read more here:
https://github.com/tailwindlabs/tailwindcss/discussions/7304#discussioncomment-2256226
Even i faced the same issue but I am using Vue3 + element-ui-plus, after spending more than 6 hours my solution is to set :native-type='null':
<el-button type='primary' round #click='handleClick' :native-type='null'>Click Me</el-button>
but this is kinda "hack", this either need to be fixed by Tailwind or by element-ui team. Anyhow, for now enjoy ;)
And the discussion is on here
I got the same issue using tailwindcss v3 and NextUI, and button's background were "transparent". By adding type = {null}, to button's I solve the issue

How to load css in react app?

I created a react app using create-react-app and everything works fine except that I can't figure out how to load css/stylus files.
In my previous react project that wasn't created using create-react-app I used webpack.config but now I don't know where to include this file and how to use it.
This is my folder structure:
.
+--client
| +--node_modules
| +--public
| +--src
| +--package.json
+--server
| +--node_modules
| +--src
| +--.babelrc
| +--package.json
This is my previous webpack.config.dev.js file:
import path from 'path';
import webpack from 'webpack';
export default {
entry: [
'webpack-hot-middleware/client?reload=true',
path.join(__dirname, '/client/index.js')
],
output: {
filename: 'bundle.js',
path: '/',
publicPath: '/'
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.HotModuleReplacementPlugin()
],
module: {
rules: [
{
test: /\.js$/,
include: path.join(__dirname, 'client'),
loader: 'babel-loader',
},
{
test: /\.styl$/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
},
],
},
{
test: /\.css?$/,
use: [
'style-loader',
{
loader: 'css-loader',
},
],
},
],
},
resolve: {
extensions: [ '.js', '.styl' ]
}
}
Please let me know if I need to provide additional information.
There is detailed informations about how to add SCSS and Less files to create-react-app project on their documentation. You can check here for more detail.
You can add basic CSS styling with just importing the file like shown below;
import '/css/main.css';
Or you can add as classNames
const styles = {
header: {
fontSize: 18,
color: '#909090',
}
};
export default class Header extends React.Component {
render() {
return (
<h1 className={styles.header}>This is a header</h1>
);
}
}
One of the approaches involves loading CSS files (via css-loader) from your JS files, for a Text.jsx
import React from 'react';
import './screen.css'; // if screen.css is located next to Text.jsx
class Text extends React.Component {
// ...
}
export default Text;
You could also generate an output CSS, using e.g. ExtractTextPlugin (see Webpack2 loading and extracting LESS file)

react, meteor, webpack, es6. How to create a loading/splash screen

I am using a build for react, es6 modules and meteor with webpack. These techs take a while to load all their stuff, before something shows up on the page. How can I with this stack show a pre-loader / splash screen while all this loads up?
my webpack file:
var autoprefixer = require('autoprefixer');
module.exports = {
entry: [
'babel-polyfill',
'./entry'
],
resolve: {
extensions: ['', '.js', '.jsx', '.json','css','scss']
},
devtool: 'eval',
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
plugins:['transform-runtime'],
presets:['es2015','stage-0','react']
}
},
{
test: /\.scss$/,
loader: 'style-loader!css-loader!sass-loader!postcss-loader'
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'url?limit=8192',
'img-loader'
]
},
]
},
postcss: [ autoprefixer({ browsers: ['last 2 versions'] }) ]
};
My entry.js file:
import '../store.js';
import './../lib/routes.jsx';
My routes.jsx file:
import React from 'react';
import {FlowRouter} from 'meteor/kadira:flow-router';
import {mount} from 'react-mounter';
import $ from 'jquery';
import store from '../store.js';
import {Provider} from 'react-redux';
import App from '../client/components/app/app.jsx';
import HomePage from '../client/components/pages/home/homePage.jsx';
import AboutPage from '../client/components/pages/about/aboutPage.jsx';
import BlogPage from '../client/components/pages/blog/blogPage.jsx';
import BlogPostPage from '../client/components/pages/blogPost/blogPostPage.jsx';
FlowRouter.route('/', {
name:"home",
action() {
mount(App, {page: <Provider store={store}><HomePage /></Provider>});
}
});
FlowRouter.route('/about', {
name:"about",
action() {
mount(App, {page: <Provider store={store}><AboutPage /></Provider>});
}
});
FlowRouter.route('/blog', {
name:"blog",
action() {
mount(App, {page: <Provider store={store}><BlogPage /></Provider>});
}
});
FlowRouter.route('/blog/:slug', {
name:"blog post",
action(params) {
console.log(params);
mount(App, {page: <Provider store={store}><BlogPostPage slug={params.slug} /></Provider>});
}
});
// this is just a work around for a problem I am having with initial rout loading in development mode.
if (!$('.app-root').length)
FlowRouter.go(window.location.href.replace(/^http(s)?\:\/\/[^:\/\#]*(\:[^\/\#]*)?\/?/,'/').replace(/\#.*$/,'')+'#'+Math.floor(Math.random()*100000));
let lastPage = FlowRouter.current();
store.subscribe(()=>{
let state = store.getState();
if (!state || state.currentURL != lastPage)
FlowRouter.go(state.currentURL);
});
After a ton of research and a lot of help from this thread: https://github.com/webpack/webpack/issues/215
I have discovered that there is no reliable way to do this, at least not what I had in mind.
The solution I used in the end was in my entry file to use the following code:
import $ from 'jquery';
$('body').addClass('css-loading-class-goes-here');
require.ensure(['../store.js', './../lib/routes.jsx'], function(require) {
require(['../store.js','./../lib/routes.jsx']);
});
You can add css, append content or whatever else you want to do at the start there, but this will only execute after alot of the 'native' javascript from webpack and friends has loaded (about 350kb in my case). Then the require.ensure enforces webpack to load all my app specific javascript in a seperate bundle after the fact, so my 'loader' is at lest active for half of the load process.
This was the only solution that I could find in the end.

How to import css file for into Component .jsx file

I am trying to use the react-day-pickers component like so but I can't figure out how to import the .css file and I keep getting the error:
Module parse failed:
/Users/qliu/Documents/workspace/AppNexus/pricing_ui/contract-ui/app_contract-ui/node_modules/react-day-picker/lib/style.css Unexpected token (3:0)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (3:0)
I have "css-loader": "^0.19.0", in my package.json installed and
here is my Calender.jsx file:
import React from "react";
import DayPicker, { DateUtils } from "react-day-picker";
import "../../../node_modules/react-day-picker/lib/style.css"; // <==== ERROR ON THIS LINE
export default class Calender extends React.Component {
state = {
selectedDay: null
};
handleDayClick(e, day, modifiers) {
if (modifiers.indexOf("disabled") > -1) {
console.log("User clicked a disabled day.");
return;
}
this.setState({
selectedDay: day
});
}
render() {
// Add the `selected` modifier to the cell of the clicked day
const modifiers = {
disabled: DateUtils.isPastDay,
selected: day => DateUtils.isSameDay(this.state.selectedDay, day)
};
return <DayPicker enableOutsideDays modifiers={ modifiers } onDayClick={ this.handleDayClick.bind(this) } />;
}
}
and this is my webpack.config.js:
var path = require('path');
var webpack = require('webpack');
var settings = require('./src/server/config/settings');
var LessPluginAutoPrefix = require('less-plugin-autoprefix');
module.exports = {
devtool: '#source-map',
resolve: {
extensions: ['', '.jsx', '.js']
},
entry: [
'webpack-hot-middleware/client',
'./src/client/index.jsx'
],
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
// to avoid duplicate import of React with react-addons-css-transition-group
'./React': 'React',
'./ReactDOM': 'ReactDOM',
config: 'config'
},
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
lessLoader: {
lessPlugins: [
new LessPluginAutoPrefix({ browsers: ['last 2 versions'] })
]
},
module: {
loaders: [{
test: /\.(js|jsx)$/,
loaders: ['babel'],
exclude: /node_modules/
},
{
test: /\.less$/,
loader: 'style!css!less'
},
{
test: /\.json$/,
loader: 'json-loader'
}]
}
};
How are you compiling this? If it's webpack, you'd probably need to bring in the style-loader and include something like this in the module.loaders array in your webpack config:
{
test: /\.css$/,
loader: "style!css"
}
Update: With the webpack.config.js now provided, we can confirm it needed a change in the module.loaders array. OP was using a less loader and only checking for .less files, so the exact loader object should read:
{
test: /\.(less|css)$/,
loader: 'style!css!less'
}
As suggested by #Q Liu. Leaving the original bit as if someone comes here with an error importing a .css file, it's likely what they need.
I used the following in my webpack config and it worked:
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
JSX is not CSS. In your main HTML file, just add a <link> element to the CSS file, and the DOM generated by React will use it.

React essence stylesheet is 14mb with webpack

I just recognized that my stylesheet is 14mb when I am using the react essence library for the UI part. Webpack is also using forever to bundle in the beginning.
I just tested this with a simple react app where I import just the essence button. The stylesheet appears to be 7mb. It looks like webpack is importing everything instead of parts.
My webpack config file is simple:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
devtool: 'eval',
entry: [
'webpack-hot-middleware/client',
'./src/index.jsx'
],
output: {
path: path.join(__dirname, 'static'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new ExtractTextPlugin('styles.css', { allChunks: true }),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('devolopment')
}
})
],
module: {
loaders: [
{
test: /\.(jsx|js)/,
loaders: ['react-hot', 'babel'],
resolve: ['.js', '.jsx'],
exclude: /node_modules/,
include: path.join(__dirname, 'src')
},
{
test: /(\.css|.less)$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader!less-loader'),
resolve:['.less', '.css']
},
{
test: /\.(otf|eot|svg|ttf|woff)/,
loader: 'url-loader'
}
]
},
resolve: {
extensions: ['', '.js', '.json', '.less', '.jsx']
}
};
What is the problem and how do I solve this?
Edit:
The webpack output when importing button from react-essence: Link
The webpack out when importing button from essence-button: Link
Depending on your Essence component import there are 2 options:
import { Btn } from react-essence will import all Essence css.
import Btn from essence-btn will import only the Essence Btn css & Essence core.
Will help me to solve this issue if you can share your code snippet so I can test/debug it.

Resources