laravel-mix-purgecss and summernote - css

I have recently added laravel-mix-purgecss to my laravel project. Its went great till I noticed it stripped all the css from Summernote. How can I exclude the css from the purge or include all the classes so Summernote works?
Note that Summernote worked fine until I used Purgecss. Also Summernote is inside a Vue Component.
Here is what I tried so far..
webpack.mix.js
let mix = require('laravel-mix');
const glob = require('glob-all');
require('laravel-mix-purgecss');
mix.js('resources/assets/js/app.js', 'public/js')
.js('resources/assets/js/app-admin.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
.sass('resources/assets/sass/app-admin.scss', 'public/css')
.purgeCss({
enabled: true,
// This code didnt help and throws a error when I 'npm run dev'
// globs: () => [
// path.join(__dirname, 'node_modules/summernote/**/*.js'),
// ],
// This code was not required. Works without it
// paths: () => glob.sync([
// path.join(__dirname, 'resources/views/**/*.blade.php'),
// path.join(__dirname, 'resources/assets/js/**/*.vue')
// ]),
extensions: ['html', 'js', 'php', 'vue']
});
Summernote is included in a .vue component
<script>
import 'summernote'
export default {
components: {
'summernote' : require('./../Summernote')
},
.....
}
</script>

Ok, So I figured it out but it's not through webpack or laravel mix. It's simply that you copy all the outputted html of summernote and paste it in a new blade file (or any file that you tell PurgeCss to look in) that you simply never use. PurgeCss will look through all your blade files and find all the classes.
So what I've done is make a master include file that will contain all classes that doesnt not already appear in all Vue or blade.php files. No need to include that file in Laravel.
This will work with any class that PurgeCss can not find in your files. Just make a div with all the classes and through that file in where the rest of your view files are.
<div class="any-misses-classes-here"></div>
That means the Code in my original post above will work. Just delete everything that is commented out.
This solutions feels kind of silly but simple. Hope this helps anyone with the same issue!

Related

Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected

I am trying to import "../../node_modules/react-quill/dist/quill.snow.css"; in my next.js project but I get following error
[ error ] ./node_modules/react-quill/dist/quill.snow.css
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to pages/_app.js.
Read more: https://err.sh/next.js/css-global
Location: components\crud\BlogCreate.js
I managed to make it work with next.config.js. It worked with this configuration
// next.config.js
const withCSS = require('#zeit/next-css');
module.exports = withCSS({
cssLoaderOptions: {
url: false
}
});
But now I am getting a warning,
Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected.
See here for more info: https://err.sh/next.js/built-in-css-disabled
It seems my solution is not the best way to solve this problem. How could I get rid of this warning?
You may remove the #zeit/next-css plugin because the Next.js 9.3 is very simple. Then Next.js 9.3 is Built-in Sass Support for Global Stylesheets after removing the #zeit/next-css you may install
npm install sass
Then, import the Sass file within pages/_app.js.
Global CSS
Import any global CSS in the /pages/_app.js.
import '../styles.css'
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
Importing CSS in components or pages won't work with the built-in CSS support.
Component CSS
Next.js supports CSS Modules using the [name].module.css file naming convention.
components/Button.module.css
/*
You do not need to worry about .error {} colliding with any other `.css` or
`.module.css` files!
*/
.error {
color: white;
background-color: red;
}
components/Button.js
import styles from './Button.module.css'
export function Button() {
return (
<button
type="button"
// Note how the "error" class is accessed as a property on the imported
// `styles` object.
className={styles.error}
>
Destroy
</button>
)
}
CSS Module files can be imported anywhere in your application.
Third-party CSS on Component / Page level
You can use <link> tag in the component.
const Foo = () => (
<div>
<link
href="third.party.css"
rel="stylesheet"
/>
</div>
);
export default Foo;
The loaded stylesheet won't be automatically minified as it doesn't go through build process, so use the minified version.
If none of the options doesn't fit your requirements consider using a custom CSS loader like #zeit/next-css.
In that case you will see a warning which is fine:
Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected.
See here for more info: https://err.sh/next.js/built-in-css-disabled
Suggested reading:
Next.js Built-In CSS Support
Global SASS
CSS Modules
Install sass module by running following command.
npm install sass
You then need to remove all css-loader and sass-loader configuration from next.config.js.
For example, I had to remove the withSass() function (in your case withCSS()) and just return the configuration object.
Had to remove the following lines from next.config.js
{
test: /\.scss$/,
use: {
loader: "sass-loader",
options: {
data: '#import "./scss/_variables.scss"',
sourceMap: true,
},
},
}
Move your options to sassOptions in next config file.
sassOptions: {
data: '#import "./scss/_variables.scss"',
sourceMap: true,
}
Also remove the old #zeit/next-sass and #zeit/next-css from package.json
I had to remove following #zeit dependency from my package.json
"dependencies": {
"#zeit/next-sass": "1.0.1",
This worked for me.
For more details, visit https://nextjs.org/docs/basic-features/built-in-css-support

Next.js Global CSS cannot be imported from files other than your Custom <App>

My React App was working fine, using global CSS also.
I ran npm i next-images, added an image, edited the next.config.js, ran npm run dev, and now I'm getting this message
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to pages/_app.js.
Read more: https://err.sh/next.js/css-global
I've checked the docs, but I find the instructions a little confusing as I am new to React.
Also, why would this error happen now? Do you think it has anything to do with the npm install?
I've tried to remove new files I've added along with their code, but this doesn't fix the problem. I've also tried what the Read more: suggests.
My highest tier component.
import Navbar from './Navbar';
import Head from 'next/head';
import '../global-styles/main.scss';
const Layout = (props) => (
<div>
<Head>
<title>Bitcoin Watcher</title>
</Head>
<Navbar />
<div className="marginsContainer">
{props.children}
</div>
</div>
);
export default Layout;
My next.config.js
// next.config.js
const withSass = require('#zeit/next-sass')
module.exports = withSass({
cssModules: true
})
My main.scss file
#import './fonts.scss';
#import './variables.scss';
#import './global.scss';
my global.scss
body {
margin: 0;
}
:global {
.marginsContainer {
width: 90%;
margin: auto;
}
}
The thing I find the weirdest is that this error came without changing anything to do with CSS, or Layout.js, and it was previously working?
I've moved my main.scss import to the pages/_app.js page, but the styles still aren't coming through. This is what the _app.js page looks like
import '../global-styles/main.scss'
export default function MyApp({ Component, props }) {
return <Component {...props} />
}
Use the built-in Next.js CSS loader (see here)
instead of legacy #zeit/next-sass.
Replace #zeit/next-sass package with sass.
Remove next.config.js. Or do not change CSS loading in it.
Move the global CSS as suggested in the error message.
Since Next.js 9.2 global CSS must be imported in Custom <App> component.
// pages/_app.js
import '../global-styles/main.scss'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
To add styles only to a specific component or page you can use built-in support of CSS modules. (see here)
For example, if you have a component Button.js you can create a Sass file button.module.scss and include it in the component.
Next.js stops complaining when your file has module in naming, e.g., changing import '../global-styles/main.scss'; to import '../global-styles/main.module.scss'; would fix the warning and you could have your styles in the global-styles, or for example, in your component.
No extra dependencies/configurations in next.config.js is required.
You can replace the opinionated (and overly-complex?) NextJs CSS loaders with your own. Here's a simple one for global css:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
reactStrictMode: true,
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// Find and remove NextJS css rules.
const cssRulesIdx = config.module.rules.findIndex(r => r.oneOf)
if (cssRulesIdx === -1) {
throw new Error('Could not find NextJS CSS rule to overwrite.')
}
config.module.rules.splice(cssRulesIdx, 1)
// Add a simpler rule for global css anywhere.
config.plugins.push(
new MiniCssExtractPlugin({
experimentalUseImportModule: true,
filename: 'static/css/[contenthash].css',
chunkFilename: 'static/css/[contenthash].css',
})
)
config.module.rules.push({
test: /\.css$/i,
use: !isServer ? ['style-loader', 'css-loader'] : [MiniCssExtractPlugin.loader, 'css-loader'],
})
return config
},
}
Add this to your _app.js
import '../styles/globals.css'
For me the problem was because I had used two module.exports in my next.config.js file like this
const withPlugins = require('next-compose-plugins')
const sass = require('#zeit/next-sass')
const css = require('#zeit/next-css')
const nextConfig = {
webpack: function(config){
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}}
})
return config
}
}
module.exports = withPlugins([
[css],
[sass, {
cssModules: true
}]
], nextConfig)
module.exports = {
env: {
MONGO_URI = 'your uri'
}
}
. 1I modified it to change the export module like this.
const nextConfig = {
webpack: function(config){
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}}
})
return config
},
env: {
MONGO_URI: "your uri"
}
}
2then I deleted the second module.exports
This node package provides a perfect solution for it. You can find it here
Steps to fix it:
1. Add package:
npm install next-remove-imports
or
yarn add next-remove-imports
2. Add this wrapper variable inside your next.config.js
const removeImports = require('next-remove-imports')({
test: /node_modules([\s\S]*?)\.(tsx|ts|js|mjs|jsx)$/,
matchImports: "\\.(less|css|scss|sass|styl)$"
});
All it is doing is re-enabling global styling import rule for tsx|ts|js|mjs|jsx files
3. Wrap your next config export with this next-remove-imports wrapper. Something like this:
module.exports = removeImports((nextConfig)
4. Now restart your react app and you will be able to import CSS files inside any ts|js|js|jsx|mjs file or component.
Try to include ".module" in your scss file name.
Change main.scss to main.module.scss
Example:
import styles from './todolist-profile-info.module.scss'
You did not need to do anything inside of next.config.js.
Let's assume you are using a global css like Bootstrap, meaning it contains css that is meant to be applied to your entire application and all the different pages inside of it.
Global css files have to be wired up to NextJS in a very particular fashion.
So inside of the pages/ directory you need to create _app.js.
It's critical that the file be named _app.js.
Then at the top of that file you would import Bootstrap css in the following manner:
import 'bootstrap/dist/css/bootstrap.css';
Then you would add the following:
export default ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
So what is going on in that code?
Well, behind the scenes, whenever you try to navigate to some distinct page with NextJS, NextJS will import your component from one of the different files inside your pages/ directory.
NextJS does not just take your component and show it on the screen.
Instead it wraps it up inside of its own custom default component and that is referred to inside of NextJS as the App.
What you are doing by defining the _app.js is to define your own custom app component.
So whenever you try to visit a route inside a browser or your root route, NextJS is going to import that given component and pass it into the AppComponent as the Component prop.
So Component there is equal to whatever components you have in the pages/ directory. And then pageProps is going to be the set of components that you are intending to pass to your files inside of pages/.
So long story short, this thing is like thin wrapper around the component that you are trying to show on the screen.
Why do you have to define this at all?
Well, if you ever want to include some global css to the project, Bootstrap being a global css for example, you can only import global css into the _app.js file.
It turns out that if you try to visit other components or other pages, NextJS does not load up or even parse those files.
So any css you may have imported inside there will not be included in the final HTML file.
So you have a global css that must be included on every single page, it has to be imported into the app file because it's the only file that is guaranteed to be loaded up every single time a user goes to your application.
Don't forget that in addition to importing the css inside of _app.js, you also have to run an npm install bootstrap in your terminal.
You can read more on this here:
https://nextjs.org/docs/messages/css-global
For me, i got this error because I had used improper naming for my project's parent folder, had used special characters in it,
like project#1,
after removing special chars, and changing the folder name to like project-1, the error got away.
In my case there was typo in navbar.module.css
I've written navbar.moduile.css
you must for every component css/scss write navbar.module.css/scss/sass.Next js doesnt compile navbar.css/scss/sass. If hope my answer helps you !.

How does NuxtJS css extraction work for generated static websites?

I am trying to generate a static website out of my (minimal) code with Nuxt. In that code, I integrate in particular the tailwindcss toolkit as well as vue2-leaflet. Upon
nuxt generate
I get two css files, one for the tailwindcss css and the other for the leaflet css. While the former file is fine and contains everything I need, the latter is pretty sparse:
.leaflet-tile-pane{z-index:200}#-webkit-keyframes leaflet-gestures-fadein{to{opacity:1}}#keyframes leaflet-gestures-fadein{0%{opacity:0}to{opacity:1}}
Of course, that makes my map render in a pretty strange way, because most of the css is missing. Here's my current nuxt.config.js:
module.exports = {
mode: 'universal',
head: {
title: pkg.name,
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
css: [
],
plugins: [
{ src: '~plugins/leaflet.js', mode: 'client' }
],
buildModules: [
'#nuxtjs/tailwindcss'
],
modules: ['#nuxtjs/apollo', 'nuxt-purgecss', ['nuxt-i18n', i18n]],
[...]
build: {
extractCSS: true,
}
}
Getting rid of the extractCSS ends up incorporating all the relevant css into the index.html. It works, but then I get the following error:
ERROR Webpack mode only works with build.extractCSS set to *true*. Either extract your CSS or use 'postcss' mode
I'm not sure I understand how that whole css extraction works. Could someone enlighten me? Why is it not working with extractCSS: true? How can I make it work? Why is it working in SPA mode but not in static mode?
You are using nuxt-purgecss which is using purgecss to strip unused CSS.
purgecss do scan HTML (or vue) files for CSS classes in use and then strip unused classes from final CSS bundle.
You can take a look at default purgecss configuration used by nuxt-purgecss here. The paths lists the paths purgecss will scan for CSS usage.
Because you are not using most of the leaflet css directly (in your components), its is necessary to configure purgecss to don't remove leaflet's css.
You can do that by whitelisting (btw not sure if "comment" method will work in Vue\Nuxt)
You can read more here and here
Not tested!!
// nuxt.config.js
{
purgeCSS: {
whitelistPatterns: [/leaflet/, /marker/]
}
}
Regarding the error message
Error message is from nuxt-purgecss module - it is clearly documented here
I don't have deep knowledge of Nuxt build process. So I just assume from the docs that extractCSS: true will use extract-css-chunks-webpack-plugin to extract all CSS to separate CSS file, while (default) extractCSS: false will use PostCSS to extract all CSS and put it directly into the <style> tag of rendered page.
All of that doesn't matter IMHO because the root problem is the use of purgecss and the solution is to configure it correctly to whitelist leaflet CSS classes....

Next.js - React SSR Cannot find module './page.scss' when rendering on the server (client side rendered works fine after saving the file)

When you're using the create-react-app package you're able to have .scss-files compiled into .css-files as you type in them. You can then do import './Header.css'; in your React component files and the styles are applied. It's easy to use your dev-tools and see where the styles are coming from.
Next.js tried to get everyone to use Styled-JSX to have your stylesheets inline inside your JSX files, similar to how web components (or Polymer) do it. I personally strongly dislike that approach.
Other problems:
Styled-JSX isn't supported in my IDE (Webstorm) (even the work-around looks awful);
Styled-JSX isn't supported in my dev-tools (Chrome) - there is no reference to what line the style is defined at;
It makes my source code look like a garbled mess;
How do I include 3rd party CSS solutions with Styled-JSX? Am I now supposed to add a <link> to my <head>? For everything external? How is that optimal usage of bandwidth? Referencing to files inside of node_modules feels awkward and bad, too.
So, just add rules to next.config.js, right?
module.exports = {
webpack: (config, { dev }) => {
config.module.rules.push(
{
test: /\.(css|scss)/,
loader: "style-loader!css-loader"
}
);
return config
}
};
And then just import './Page.scss'; (Don't worry, it's valid CSS, not even SASS yet, I know I did not include the sass-loader here just yet. I try to keep it simple first.)
Refresh the page (Server Side Rendered): does NOT work;
Save the file (dynamically loaded after saving the file): it does work (until you reload the page);
Keeps complaining the file can't be found, plenty of Google hits there, too. No real solutions that work today.
So, why doesn't it work with SSR?
Note that v5 of next.js will support CSS/Sass/Less almost out of the box:
For importing .css .scss or .less we’ve created modules which have sane defaults for server side rendering.
Until then, the following set of rules worked for me (assuming the .sass files are in /styles dir):
config.module.rules.push(
{
test: /\.(css|sass)/,
loader: 'emit-file-loader',
options: {
// this path is relative to the .next directory
name: 'dist/[path][name].[ext]'
}
},
{
test: /\.css$/,
use: ['babel-loader', 'raw-loader', 'postcss-loader']
},
{
test: /\.sass$/,
use: ['babel-loader', 'raw-loader', 'postcss-loader',
{ loader: 'sass-loader',
options: {
includePaths: ['styles', 'node_modules']
.map((d) => path.join(__dirname, d))
.map((g) => glob.sync(g))
.reduce((a, c) => a.concat(c), [])
}
}
]
}
)

With Webpack, is it possible to generate CSS only, excluding the output.js?

I'm using Webpack with the extract-text-webpack-plugin.
In my project, I have some build scripts. One of the build scripts is supposed to bundle and minify CSS only. As I'm using Webpack for the other scripts, I found it a good idea to use Webpack even when I only want to bundle and minify CSS.
It's working fine, except that I can't get rid of the output.js file. I don't want the resulting webpack output file. I just want the CSS for this particular script.
Is there a way to get rid of the resulting JS? If not, do you suggest any other tool specific for handling CSS? Thanks.
There is an easy way, no extra tool is required.
There is an easy way and you don't need extra libraries except which you are already using: webpack with the extract-text-webpack-plugin.
In short:
Make the output js and css file have identical name, then the css file will override js file.
A real example (webpack 2.x):
import path from 'path'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
const config = {
target: 'web',
entry: {
'one': './src/one.css',
'two': './src/two.css'
},
output: {
path: path.join(__dirname, './dist/'),
filename: '[name].css' // output js file name is identical to css file name
},
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
},
plugins: [
new ExtractTextPlugin('[name].css') // css file will override generated js file
]
}
Unfortunately, that is currently not possible by design. webpack started as a JavaScript bundler which is capable of handling other "web modules", such as CSS and HTML. JavaScript is chosen as base language, because it can host all the other languages simply as strings. The extract-text-webpack-plugin is just extracting these strings as standalone file (thus the name).
You're probably better off with PostCSS which provides various plugins to post-process CSS effectively.
One solution is to execute webpack with the Node API and control the output with the memory-fs option. Just tell it to ignore the resulting js-file. Set the output.path to "/" in webpackConfig.
var compiler = webpack(webpackConfig);
var mfs = new MemoryFS();
compiler.outputFileSystem = mfs;
compiler.run(function(err, stats) {
if(stats.hasErrors()) { throw(stats.toString()); }
mfs.readdirSync("/").forEach(function (f) {
if(f === ("app.js")) { return; } // ignore js-file
fs.writeFileSync(destination + f, mfs.readFileSync("/" + f));
})
});
You can clean up your dist folder for any unwanted assets after the done is triggered. This can be easily achieved with the event-hooks-webpack-plugin
//
plugins: [
new EventHooksPlugin({
'done': () => {
// delete unwanted assets
}
})
]
Good Luck...

Resources