Using LESS CSS with the latest Create React App - css

It seems like everything i'm finding online is old and doesn't seem to work for me.. Any help is appreciated.
I ran "npm run eject". Then I installed with NPM
"devDependencies": {
"less": "^3.12.2",
"less-loader": "^6.2.0"
},
and in my "webpack.config.js" file this is how i have it so far:
module: {
strictExportPresence: true,
rules: [
{
test: /\.less$/,
loader: 'less-loader', // compiles Less to CSS
},
// Disable require.ensure as it's not a standard language feature.
{ parser: { requireEnsure: false } },
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
enforce: 'pre',
use: [
{
options: {
cache: true,
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'),
resolvePluginsRelativeTo: __dirname,
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
and then i get this error message when trying to run:
Failed to compile ./src/styles/index.less
(./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./node_modules/file-loader/dist/cjs.js??ref--7-oneOf-7!./src/styles/index.less)
module.exports = webpack_public_path +
"static/media/index.1f54121a.less";
^ Unrecognised input
Error in G:\Work Projects\uno\src\styles\index.less (line 1, column 15)

Hopefully this helps someonme. I found the answer here: https://segmentfault.com/a/1190000018858055
Short Version:
const cssRegex = /\.(css|less)$/;
const cssModuleRegex = /\.module\.(css|less)$/;
...
...
...
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex, // edited to add less above
exclude: cssModuleRegex, // edited to add less above
use: getStyleLoaders({
importLoaders: 2, // changed from 1 to 2
modules: true, // added this line
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'less-loader'),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
// etc

Related

Duplicating css var. First time with correct value and second time just like var(--variable). Why? (React, webpack, css)

I have next css which I include in js file:
:root {
--annotation-unfocused-field-background: url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
}
.annotationLayer .textWidgetAnnotation textarea {
background-image: var(--annotation-unfocused-field-background);
}
and after generation from webpack I get next css bundle and it duplicate:
.annotationLayer .textWidgetAnnotation textarea {
background-image: url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
background-image: var(--annotation-unfocused-field-background);
my webpack.common.js:
module: {
rules: [
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: /\.css$/,
exclude: cssModuleRegex,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: require.resolve('css-loader'),
options: cssOptions,
}
],
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
why it duplicate?
Here is the root couse:
{
// Options for PostCSS as we reference these options twice
// Adds vendor prefixing based on your specified browser support in
// package.json
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebook/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
// Adds PostCSS Normalize as the reset css with default options,
// so that it honors browserslist config in package.json
// which in turn let's users customize the target behavior as per their needs.
postcssNormalize(),
PrefixWrap(".test", {
ignoredSelectors: [":root"],
})
],
sourceMap: true,
},
},
postcss-preset-env do this duplicates. I passed number 4 into stage and level of polyfill become stable.

How to Minify CSS with Webpack when using Tailwind

When using ReactJS, Tailwind suggests using CRACO (Create React App Configuration Override). My best attempt based on this blog post on minifying css names and the CRACO docs has led me to trying the craco.config.js file below. But it still doesn't work with Tailwind.css. Tried it in both the commented locations independently.
Has anyone been able to minify/obfuscate css classnames when using TailwindCSS either via webpack or an external package? Please detail your config file or some step by step instruction if so, as I've been spending months trying to figure this out...
// craco.config.js
module.exports = {
style: {
postcss: {
plugins: [require('tailwindcss'), require('autoprefixer')],
// loaderOptions: {
// modules: {
// localIdentName: '[sha1:hash:hex:4]'
// },
// importLoaders: 1
// },
},
// css: {
// loaderOptions: {
// modules: {
// localIdentName: '[sha1:hash:hex:4]'
// },
// importLoaders: 1
// },
// }
},
};
You can minify your CSS by adding cssnano as a PostCSS plugin as follows:
// craco.config.js
module.exports = {
style: {
postcss: {
// add cssnano as a plugin here
plugins: [require('tailwindcss'), require('autoprefixer'), require('cssnano')],
// loaderOptions: {
// modules: {
// localIdentName: '[sha1:hash:hex:4]'
// },
// importLoaders: 1
// },
},
// css: {
// loaderOptions: {
// modules: {
// localIdentName: '[sha1:hash:hex:4]'
// },
// importLoaders: 1
// },
// }
},
};
Make sure to also install cssnano with npm or yarn.
Obfuscating Tailwind CSS is significantly harder than just minifying it, and in my opinion it's probably not worth the effort. However, there have been discussions on obfuscation before.

Using relative paths in SASS background images

I'm trying to get background images to work in my Angular project's SASS when I don't know where the application root will be. For example, the app's home page could be:
localhost:9000/home
or
localhost:9000/foo/home
or
localhost:9000/bar/home
I figured I could address this by just making the paths in my background-image properties relative, like this:
div {
background-image: url("assets/smiley.png");
}
However, that doesn't work. When I compile the app, it can't find the assets. In the console, it says:
Error: Can't resolve './assets/smiley.png'
It gives me this same message whether my background-image url value starts with ./ or not. But even ./ I imagine should work.
What DOES work is if I hard-code the path into the background-image property, making the path ABSOLUTE, like so:
div {
background-image: url("/foo/assets/smiley.png");
}
However, that's not an option, since I don't know if the app root will be at /foo/ or /bar/ or something else.
Another thing that works is using the --base-href option of ng build to hard-code the path, like so:
ng build --base-href /foo/
But if possible, I'd really like to accomplish this with code changes that don't involve passing parameters to the ng build command on a build-by-build basis.
Here is my Webpack Config located at node_modules/#angular/cli/models/webpack-config.js. Is that the right file? Sorry if it's not - I'm pretty unfamiliar with webpack:
/**
* Adapted from angular2-webpack-starter
*/
const helpers = require('./config/helpers'),
webpack = require('webpack');
/**
* Webpack Plugins
*/
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
module.exports = {
devtool: 'inline-source-map',
resolve: {
extensions: ['.ts', '.js']
},
entry: helpers.root('ng2-translate.ts'),
output: {
path: helpers.root('bundles'),
publicPath: '/',
filename: 'ng2-translate.umd.js',
libraryTarget: 'umd',
library: 'ng2-translate'
},
// require those dependencies but don't bundle them
externals: [/^\#angular\//, /^rxjs\//],
module: {
rules: [{
enforce: 'pre',
test: /\.ts$/,
loader: 'tslint-loader',
exclude: [helpers.root('node_modules')]
}, {
test: /\.ts$/,
loader: 'awesome-typescript-loader?declaration=false',
exclude: [/\.e2e\.ts$/]
}]
},
plugins: [
// fix the warning in ./~/#angular/core/src/linker/system_js_ng_module_factory_loader.js
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
helpers.root('./src')
),
new webpack.LoaderOptionsPlugin({
options: {
tslintLoader: {
emitErrors: false,
failOnHint: false
}
}
})
]
};

Webpack 1.15.0 FeathersJS React Redux Material-UI styles not compiled or present in rendered DOM

been having a tremendously difficult time determining why my stylesheets seem to be ignored in a package I am trying to modify for my own use. Not sure if this is a problem with Material-UI or Webpack itself, but any require or import statements I add to the head of any .js doc throw errors when running build script. The same imports for 'import style from './style.css' works in documents from original repository.
Best I am able to analyze the Webpack configs I am using seem to disregard any stylesheets except those a handful that were included with the original package AND any modifications within stylesheets that do render to the DOM are also disregarded. Everything I have researched indicates that this config works, and throws no errors when I run the corresponding build script.
Please help! Thank you!
webpack.production.configjs
/* eslint-env node */
/* eslint no-console: 0, no-var: 0 */
// Webpack config for PRODUCTION and DEVELOPMENT modes.
// Changes needed if used for devserver mode.
const webpack = require('webpack');
const rucksack = require('rucksack-css');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const envalid = require('envalid');
const path = require('path');
// Validate environment variables
validateEnvironmentVariables();
const config = require('config');
if (config.NODE_ENV === 'devserver') {
throw new Error('This webpack config does not work as is with the web-dev-server.')
}
const isProduction = config.isProduction;
const outputPublicPaths = {
production: '/dist/',
development: '/dist/',
devserver: 'http://localhost:8080/', // we don't use this config for webpack-dev-server
};
console.log(`----- ${config.NODE_ENV.toUpperCase()} build.`); // eslint-disable-line no-console
// Base Webpack configuration
const webpackConfig = {
context: path.join(__dirname, 'client'),
// re devtool: http://cheng.logdown.com/posts/2016/03/25/679045
devtool: isProduction ? 'cheap-module-source-map' : 'source-map',
entry: {
main: ['./index.js'],
// Webpack cannot produce chunks with a stable chunk hash as of June 2016,
// stable meaning the hash value changes only when the the code itself changes.
// See doc/FAQ.md#webpackChunks.
// This vendor chunk will not reduce network requests, it will likely force a second request
// each time the main chunk changes. So why separate them?
// Chunks for code which is dynamically optionally loaded makes sense.
// The first page will render faster as the parsing of such chunks can be delayed
// till they are needed.
// Of course the React routing must be changed to load such chunks as needed.
// Maybe we'll make the routing do that at some time.
/*
user: [
// './screens/Users/UserSignIn', // sign in occurs often enough to retain in main chunk
'./screens/Users/UserEmailChange',
'./screens/Users/UserForgotPwdReset',
'./screens/Users/UserForgotPwdSendEmail',
'./screens/Users/UserPasswordChange',
'./screens/Users/UserProfile',
'./screens/Users/UserProfileChange',
'./screens/Users/UserRolesChange',
'./screens/Users/UserSignIn',
'./screens/Users/UserSignInPending',
'./screens/Users/UserSignUp',
'./screens/Users/UserSignUpSendEmail',
'./screens/Users/UserSignUpValidateEmail',
],
*/
},
output: {
filename: '[name].bundle.[chunkhash].js',
// Tell Webpack where it should store the resulting code.
path: path.join(__dirname, 'public', 'dist'),
// Give Webpack the URL that points the server to output.path
publicPath: outputPublicPaths[config.NODE_ENV],
},
/* This is needed for joi to work on the browser, if the client has that dependency
node: {
net: 'empty',
tls: 'empty',
dns: 'empty',
},
*/
module: {
loaders: [
{
// File index.html is created by html-webpack-plugin. It should be a file webpack processes.
test: /\.html$/,
loader: 'file?name=[name].[ext]',
},
{
// When require'd, these /client/../*.inject.css files are injected into the DOM as is.
test: /\.inject\.css$/,
include: /client/,
loader: 'style!css',
},
{
// When required, the class names in these /client/../*.css are returned as an object.
// after being made unique. The css with the modified class names is injected into the DOM.
test: /^(?!.*\.inject\.css).*\.css$/,
include: /client/,
loaders: [
'style-loader',
'css-loader'
],
},
{
// Standard processing for .css outside /client
test: /\.css$/,
exclude: /client/,
loader: 'style!css',
},
{
test: /\.(js|jsx)$/, // does anyone still use .jsx?
exclude: /(node_modules|bower_components)/,
loaders: [
/*
'react-hot',
*/
'babel-loader',
],
},
{
test: /\.(svg|woff|woff2|ttf|eot)$/,
loader: 'file?name=assets/fonts/[name].[hash].[ext]'
},
],
},
resolve: {
extensions: ['', '.js', '.jsx'],
// Reroute import/require to specific files. 'react$' reroutes 'react' but not 'react/foo'.
alias: {
},
},
postcss: [
rucksack({
autoprefixer: true,
}),
],
plugins: [
// Webpack's default file watcher does not work with NFS file systems on VMs,
// definitely not with Oracle VM, and likely not with other VMs.
// OldWatchingPlugin is a slower alternative that works everywhere.
new webpack.OldWatchingPlugin(), // can use "webpack-dev-server --watch-poll" instead
/*
Build our HTML file.
*/
// repeat new HtmlWebpackPlugin() for additional HTML files
new HtmlWebpackPlugin({
// Template based on https://github.com/jaketrent/html-webpack-template/blob/master/index.ejs
template: path.join(process.cwd(), 'server', 'utils', 'index.ejs'),
filename: 'index.html',
inject: false, // important
minify: {
collapseWhitespace: true,
conservativeCollapse: true,
minifyCSS: true,
minifyJS: true,
preserveLineBreaks: true, // leave HTML readable
},
cache: false,
/* We'd need this if we had a dynamically loaded user chunk
excludeChunks: ['user'],
*/
// Substitution values
supportOldIE: false,
meta: { description: config.client.appName },
title: config.client.appName,
faviconFile: '/favicon.ico',
mobile: false,
links: [],
baseHref: null,
unsupportedBrowserSupport: false,
appMountId: 'root',
appMountIds: {},
addRobotoFont: true, // See //www.google.com/fonts#UsePlace:use/Collection:Roboto:400,300,500
copyWindowVars: {},
scripts: ['/socket.io/socket.io.js'],
devServer: false,
googleAnalytics: false,
}),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify(config.NODE_ENV) }, // used by React, etc
__processEnvNODE_ENV__: JSON.stringify(config.NODE_ENV), // used by us
}),
],
};
// Production customization
if (isProduction) {
webpackConfig.plugins.push(
/*
Besides the normal benefits, this is needed to minify React, Redux and React-Router
for production if you choose not to use their run-time versions.
*/
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false },
comments: false,
sourceMap: false,
mangle: true,
minimize: true,
verbose: false,
})
);
}
module.exports = webpackConfig;
// Validate environment variables
function validateEnvironmentVariables() {
const strPropType = envalid.str;
// valid NODE_ENV values.
const nodeEnv = {
production: 'production',
prod: 'production',
development: 'development',
dev: 'development',
devserver: 'devserver',
testing: 'devserver',
test: 'devserver',
};
const cleanEnv = envalid.cleanEnv(process.env,
{
NODE_ENV: strPropType({
choices: Object.keys(nodeEnv),
default: 'developmwent',
desc: 'processing environment',
}),
}
);
process.env.NODE_ENV = nodeEnv[cleanEnv.NODE_ENV];
}
Just at a first glance, you need to add -loader to each loader. You've done it for one, but not the other two:
{
// When require'd, these /client/../*.inject.css files are injected into the DOM as is.
test: /\.inject\.css$/,
include: /client/,
loaders: [
'style-loader',
'css-loader'
]
},
{
// When required, the class names in these /client/../*.css are returned as an object.
// after being made unique. The css with the modified class names is injected into the DOM.
test: /^(?!.*\.inject\.css).*\.css$/,
include: /client/,
loaders: [
'style-loader',
'css-loader'
],
},
{
// Standard processing for .css outside /client
test: /\.css$/,
exclude: /client/,
loaders: [
'style-loader',
'css-loader'
]
},

How does one deploy a ReactJs component that imports its own stylesheets?

I'm developing a large React component that I want to import into another React app. (I could have done it all as one big app, but I decided to separate this component into a its own project so that I could focus on the component separately.) It uses its own stylesheets, which it pulls in with "require('path/to/stylesheet.[s]css')".
For development, I serve it with webpack-dev-server which takes care of loading and pre-processing those stylesheets. My problem is that I don't know how to deploy the component so that another app can include it without breaking when the browser encounters those calls to require(path/to/stylesheet).
I've found lots of examples where projects use webpack-dev-server for development, but invoke babel (or other pre-processors) directly in order to deploy components to a dist/ directory, so this seems to be a common practice. But what to do about those invocations of "require('path/to/stylesheet.[s]css')"? Without webpack and its loaders to rely on, they all fail.
Ideally, I'd like to be able to use webpack for both development and production. Then I could deploy my component as a complete bundle and the css would be included in the code. I tried this earlier but it didn't work. It also has the disadvantage of making it hard for the main app to over-ride the styles in the component.
I suppose another way might be to set up my pipeline so that a main.scss includes all the other stylesheets and let Sass output a single style.css file that the consuming app has to include separately. Less elegant, but it makes it easier to override these styles.
I'm still mastering React and its eco-system, so I'd love to know what the best practice is for this in case anyone knows.
You need to run webpack and bundle all of your JS/CSS so that it can be consumed in your other project. If you use the correct loaders, the CSS is bundled directly into your JS bundle. Or, you can use a different loader to have webpack generate you a nice style.css file that bundles all your require(/path/to/css) into one file.
There are three or four basic things you need to do (Assuming webpack#3.*):
Use the "externals" in your webpack config file to exclude libraries in your package.json dependencies list.
Use babel-loader to transpile your javascript (ES2015 is supported by most browsers).
Use 'style-loader', 'css-loader', and 'sass-loader' to bundle your css/scss into your webpack js bundle. (This assumes you aren't using server-side react rendering. That's a bit trickier. You would need to use an isomorphic style loader instead.)
Optionally, use the extract-text-webpack-plugin to pull your css out into a separate file. (Commented out in the example below)
Be sure to make your bundle.js file the entry point in your package.json
Here is a good example of what you are trying to do: (This example works for server-side rendering as well as browser rendering. The BABEL_ENV lets us only require css files on the browser.)
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const env = process.env.NODE_ENV;
console.log('Environment: ', env)
module.exports = {
devtool: 'source-map',
entry: env == 'production' ? './src/components/index.js' : './src/index.js',
output: {
path: env !== 'production' ? require('path').resolve('./dev'): require('path').resolve('./dist'),
filename: 'bundle.js',
publicPath: '/',
library: 'reactPorto',
libraryTarget: 'umd'
},
externals: env == 'production' ? [
'jquery',
'react',
'react-dom',
'react-bootstrap',
/^react-bootstrap\/.+$/,
'classnames',
'dom-helpers',
'react-owl-carousel',
'react-owl-carousel2',
'uncontrollable',
'warning',
'keycode',
'font-awesome'
] : [],
devServer: {
inline: true,
contentBase: './dev',
staticOptions: { index: 'test.html' },
historyApiFallback: {
rewrites:[{ from: /./, to: 'test.html' }],
},
hot: true,
},
plugins: [
// new ExtractTextPlugin({
// filename: 'style.css',
// allChunks: true
// }),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(env || 'development'),
'BABEL_ENV': JSON.stringify(env || 'development')
}
}),
new webpack.optimize.OccurrenceOrderPlugin(),
...(env != 'production' ? [new webpack.HotModuleReplacementPlugin()] : []),
...(env == 'production' ? [new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } })] : []),
new webpack.NoEmitOnErrorsPlugin()
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
query: {
presets: [
'es2015',
'react',
'stage-2',
...(env != 'production' ? ['react-hmre'] : [])
],
plugins: []
}
}
},
{
test : /(\.css|\.scss)/,
// exclude: /node_modules/,
// use : ExtractTextPlugin.extract({
// use: [
// 'isomorphic-style-loader',
// {
// loader: 'css-loader',
// options: {
// importLoaders: 1
// }
// },
// 'sass-loader'
// ]
// }),
use: ['iso-morphic-style-loader', 'css-loader', 'sass-loader']
},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader?mimetype=image/svg+xml'},
{test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/octet-stream"},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader"},
{test: /\.(png|jpg|jpeg)/, loader: 'file-loader' }
]
}
}

Resources