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.
Related
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.
Before the changes, everything was going to build and everything worked.
my next.config.js //
// const withCss = require('#zeit/next-css');
// const withSass = require('#zeit/next-sass');
class TailwindExtractor {
static extract(content) {
return content.match(/[A-Za-z0-9-_:\/]+/g) || [];
}
}
const nextConfig = {
...
};
module.exports = withPlugins([
// [ withSass, {} ],
// [ withCss, {} ],
[ withPurgeCss, {
...
}
], nextConfig);
Further, as recommended, I decided to abandon the use of the deprecated # zeit / next-css and # zeit / next-sass
I added the tailwind.config.js file as written on their website:
module.exports = {
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
};
And made changes to post.config.js and also installed the missing packages:
module.exports = {
plugins: {
'postcss-import': {},
tailwindcss: {},
autoprefixer: {},
'postcss-preset-env': { stage: 2 },
},
};
In _app.js, I include the main.scss file:
#import "tailwindcss/preflight";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
.self-class {
#apply .bg-olive .shadow-olive .text-base .text-white .font-bold;
}
I get an error: Error: Syntax error: /home/roma/project/main.scss #applycannot be used with.bg-olivebecause.bg-oliveeither cannot be found, or its actual definition includes a pseudo-selector like :hover, :active, etc. If you're sure that.bg-oliveexists, make sure that any#importstatements are being properly processed *before* Tailwind CSS sees your CSS, as#apply can only be used for classes in the same CSS tree.
Do I have my tailwind.config.js file configured incorrectly or is the file built incorrectly in general? So where I am trying to refer to tailwind styles is not known about them yet?
Thanks for any help!
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
I'm using Next.JS with a few other modules. One of them, Megadraft, comes with its own CSS. I don't know if this is relevant, but I also use PurgeCSS.
Everything works fine on development mode, but the CSS seems to break in production mode. To be a little more explicit, all of the classes of Megadraft, seem to have no definition in production mode.
The HTML nodes in the inspector still show that the classes are here, but they have just no definition.
Here's how I import the said CSS files in my pages/_app.js file:
// pages/_app.js
import "css/tailwind.css";
import "megadraft/dist/css/megadraft.css";
And this is my postcss.config.js:
// postcss.config.js
const purgecss = [
"#fullhuman/postcss-purgecss",
{
content: [
"./components/**/*.js",
"./Layout/**/*.js",
"./pages/**/*.js",
"./node_modules/next/dist/pages/**/*.js",
"./node_modules/next/dist/Layout/**/*.js",
"./node_modules/next/dist/components/**/*.js"
],
defaultExtractor: (content) => content.match(/[A-Za-z0-9-_:/]+/g) || [],
},
];
module.exports = {
plugins: [
"postcss-import",
"tailwindcss",
"autoprefixer",
...(process.env.NODE_ENV === "production" ? [purgecss] : []),
],
};
I'm using next ^9.4.4. It may be worth noticing that TailwindCSS seems to work just fine (both in dev and prod), but I think it may be because it is used as a plugin in postcss...
Just in case also, I integrated webpack to my project to solve an error I had where the code was telling that I needed a loader:
// next.config.js
module.exports = {
cssModules: true,
webpack: (config, options) => {
config.node = {
fs: "empty",
};
config.module.rules.push({
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
use: [
options.defaultLoaders.babel,
{
loader: "url-loader?limit=100000",
},
{
loader: "file-loader",
},
],
});
return config;
},
};
Anyway, if someone has an idea of why this works in development mode and not in production, it could be of great help.
Option 1: use Tailwind CSS built-in PurgeCSS
// tailwind.config.css
module.exports = {
purge: ["./components/**/*.js", "./pages/**/*.js"],
theme: {
extend: {}
},
variants: {},
plugins: []
};
// postcss.config.js
module.exports = {
plugins: ["tailwindcss", "postcss-preset-env"]
};
Be sure to add postcss-preset-env to the package's dev dependencies with npm i --save-dev postcss-preset-env or yarn add -D postcss-preset-env.
Option 2: Manually setup purge and add "./node_modules/megadraft/dist/**/*.css" to purgecss whitelisting content array:
// tailwind.config.css
module.exports = {
theme: {
extend: {}
},
variants: {},
plugins: []
};
// postcss.config.js
const purgecss = ['#fullhuman/postcss-purgecss',{
content: ["./node_modules/megadraft/dist/**/*.css", "./components/**/*.js", "./pages/**/*.js"],
defaultExtractor: content => {
const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || []
const innerMatches = content.match(/[^<>"'`\s.()]*[^<>"'`\s.():]/g) || []
return broadMatches.concat(innerMatches)
}
}]
module.exports = {
plugins: [
'tailwindcss',
'autoprefixer',
...process.env.NODE_ENV === 'production'
? [purgecss]
: []
]
}
There may be better solutions but these two are what I can think of.
I made some apps that wrapper some site with custom css. but image is not shown.
This is my webpack.config.js module part.
module: {
rules: [
{
test: /\.css$/,
loaders: ['css-loader']
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url-loader',
options: {
limit: 1000000 // 1000kb
}
}
]
},
}
Css look like this
.menu {
background-images: url("images/menu.png");
}
Some of issue with jQuery and Security(External Sites!), I put nodeIntegration: false in webPreferences
const css = require('./foo.css');
// ..
webContents.insertCSS(css.toString());
but launch a app, image is not shown. in console, I got this background-images url
background-image: url(data:image/jpeg;png,bW9kdWxl //...
decode base64 result is
module.exports = "data:image/png;base64 //...
I think module.exports cause this(Edit 3: Uncaught ReferenceError: module is not defined in console), because nodeIntegration: false
Is there any option to remove module.exports = in css-loader with other loaders? (or just turn nodeIntergration to true)?
It is same result on file-loader.
Edit 1: In my package.json: "css-loader": "^0.28.7", "url-loader": "^0.6.2", "webpack": "^3.8.1"
Edit 2: Maybe cuase by this in css-loader?