Gatsby set sass lint - css

I want sass linter in Gatsby's project
plugins: [
`gatsby-plugin-styled-components`,
{
resolve: `gatsby-source-contentful`,
options: {
},
},
{
resolve: "gatsby-plugin-eslint",
options: {
},
},
`gatsby-plugin-sass`
],
How to include it?
I want to detect incorrect CSS rules etc...

ESlint is a JavaScript linter, so it can't analyze nor lint your Sass code.
However, you can use Stylelint to parse SCSS, Saas, or CSS files.
You can follow the default configuration steps in their GitHub:
Install it by:
npm install --save --dev #primer/stylelint-config
Add a stylelintrc.json file in the root of your project (it can be a .yml or .js format too if needed)
Add your configuration rules. You can inherit from the default ones by using the extends rule as:
{
"extends": "stylelint-config-standard",
"rules": {
"indentation": "tab",
"number-leading-zero": null
}
}
Customize your commands to trigger your lint rules (change the file extension accordingly):
npx stylelint "**/*.css"
Resources:
https://stylelint.io/user-guide/get-started
https://dev.to/stories_of_ren/switching-from-sass-lint-to-stylelint-5f8c

Related

Set Global Styles Without Class Hashing in Nuxt

I have numerous Vue SPAs in a monorepo that all share a common set of global styles, each SPA and the styles are their own package.json workspace. I'm trying to replace one of them with Nuxt.
The global styles are .scss files, they import Vue bootstrap and have some custom variables and classes.
As such, I did a fresh install of Nuxt and then ran:
yarn add -D sass sass-loader#10 fibers
I know I can get global styles like so:
//in nuxt.config.js:
css: [resolve(__dirname+'/../common/styles/index.scss')
Really I thought that should/would be it, and I see it does get injected into the page. However, the class names are hashed, so it doesn't apply to my components.
Instead of this (fake css to test if it goes in the page):
.test{
text-align: test;
top: test;
}
I get this:
.olAmdkaWN_JnK1npjbKiI {
text-align: test;
top: test;
}
How can I stop the global styles from being hashed like this, especially when I may be importing components from the other SPAs/common and their classnames aren't being hashed in the HTML? Only the injected global styles are getting hashed like this.
I've tried various attempts at setting the localIdentName such as:
//in nuxt.config.js
build: {
extend(config) {
config.module.rules.push({
test: /\.scss$/,
use: [{
loader: 'css-loader',
options: {
modules: false
/*
or sometimes I'll try something like:
modules:{
localIdentName: '[local]'
}
*/
}
},
{
loader: 'sass-loader'
}
]
})
},
I've also set:
cssModules: {
localIdentName: '[local]'
},
Again in the nuxt.config.js. But nothing works and furthermore I think I must have a conceptual error about how global styles are meant to work, as I feel like I'm fighting the framework rather than working with it.
My nuxt, webpack and sass-loader verisons are as follows:
nuxt#2.15.4
webpack#4.46.0
sass-loader#10.1.1 (It was at 7.1.x but the console suggested upgrading it - didn't make a difference in terms of solving this)
package.json:
"dependencies": {
"core-js": "^3.9.1",
"common": "1.0.0", (local dependency)
"nuxt": "^2.15.3"
},
"devDependencies": {
"fibers": "^5.0.0",
"sass": "^1.32.11",
"sass-loader": "10"
}
Turns out all I needed was this (the key was to put it in loaders within build):
//in nuxt.config.js
build: {
loaders: {
cssModules: {
localIdentName: '[local]'
},
},
}
Please note this only works if you properly install your dependencies and heed build warnings in regards to css-loader and sass-loader. I tried downgrading sass-loader and this didn't work until I put it back at "10" which is what Nuxt expected (threw a warning).

Stylelint output does not show the name of the file where warnings occur

When running stylelint the output of warnings does not show the name of the file where the error occurs (with errors it does work fine). My files look like this:
app.scss
#import './_file-with-error';
_file-with-error.scss
html body {
color: red;
}
body { // provocate an error 😈
color: red;
}
I use Webpack Encore and stylelint as a PostCSS plugin, when I build I get:
michael#machine:~$ yarn encore dev
yarn run v1.21.1
$ /var/www/html/mop/mop/node_modules/.bin/encore dev
Running webpack ...
WARNING Compiled with 1 warnings 11:47:14 PM
warning in ./assets/scss/app.scss
Module Warning (from ./node_modules/postcss-loader/src/index.js):
Warning
(5:1) Expected selector "body" to come before selector "html body" (no-descending-specificity)
Entrypoint app [big] = runtime.js vendors~app.js app.css app.js
Entrypoint home = runtime.js home.js
Entrypoint _tmp_copy = runtime.js
Done in 3.06s.
So everything is fine just that I do not see where the warning comes from, I need the filename and the line. How can I configure that?
Setup
webpack.config.js
Encore.enablePostCssLoader();
postcss.config.js
module.exports = {
plugins: {
autoprefixer: {},
stylelint: {},
},
};
.stylelintrc.json
{
"extends": "stylelint-config-standard",
"rules": {
"no-duplicate-selectors": null
}
}
You need to add a reporter to your PostCSS pipeline:
The stylelint plugin registers warnings via PostCSS. Therefore, you'll want to use it with a PostCSS runner that prints warnings or another PostCSS plugin whose purpose is to format and print warnings (e.g. postcss-reporter).
For example:
module.exports = {
plugins: {
autoprefixer: {},
stylelint: {},
'postcss-reporter': { clearReportedMessages: true }
},
}
Alternatively, you can use the official webpack plugin for stylelint.

Is there a way to improve performance of scss file loading in NativeScript?

I've inherited a NativeScript app that chooses its root .scss file on startup. The loading and processing of this is taking about 10 seconds on an iPhone 6 and about 5 seconds on an iPhone XR. Does anyone have any suggestions on how I can cut this down?
I'm using the latest NativeScript CLI (6.1.2).
I've profiled it using Inspector and it seems to bottom out at evaluating a regular expression (this was done on an iPhone XR where it took about 5 seconds):
https://i.imgur.com/NufRd6u.png
Here's the code that is taking the time:
import * as app from "tns-core-modules/application";
...
if (DeviceSettings.isTablet) {
app.setCssFileName('./app.tablet.scss');
} else {
app.setCssFileName('./app.default.scss');
}
I have managed to halve the time it takes to load my .scss file by using a postcss-loader step, which puts the css through cssnano as follows:
Add the following npm packages to the project:
npm install postcss-loader --save-dev
npm install postcss-import --save-dev
npm install postcss-preset-env --save-dev
npm install cssnano --save-dev
Add a postcss.config.js file at the same level as the main package.json file with the following contents:
module.exports = {
plugins: {
'postcss-import': {},
'postcss-preset-env': {},
'cssnano': {
preset: ['default', {
normalizeUrl: false
}]
}
}
}
In webpack.config.js, add a postcss-loader after css-loader to the list of loaders for .css and .scss files:
{
test: /\.css$/,
use: [
{ loader: "css-loader", options: { url: false } },
"postcss-loader"
]
},
{
test: /\.scss$/,
use: [
{ loader: "css-loader", options: { url: false } },
"postcss-loader",
"sass-loader"
]
},
Note: I had to use the normalizeUrl: false option on cssnano, to prevent it messing with resource urls, e.g. background-image: url("res://background");, otherwise the background image would not appear.
To get any further improvements, my plan is to take any page-specific .scss files out of the global app.???.scss files and add them when the page loads, i.e. by using this.page.addCssFile().

Add SCSS support to Vue project

In my packages.json file by default I get:
"postcss": {
"plugins": {
"autoprefixer": {}
}}
When I add <style lang='scss'> It doesn't compile like magic like it does for Typescript support. I know I will need to specify some NPM package as devDependencies and specify something above in the postcss section to get scss to compile, but I can't find any documentation outside of webpack so I am lost.
See https://vue-loader.vuejs.org/guide/pre-processors.html.
For example, to compile our <style> tag with SASS/SCSS:
npm install -D sass-loader node-sass
In your webpack config:
module.exports = {
module: {
rules: [
// ... other rules omitted
// this will apply to both plain `.scss` files
// AND `<style lang="scss">` blocks in `.vue` files
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
}
]
},
// plugin omitted
}
Now in addition to being able to import 'style.scss', we can use SCSS
in Vue components as well:
<style lang="scss"> /* write SCSS here */ </style>
Any content inside the block will be processed by webpack as if it's
inside a *.scss file.

Webpack 2: compile SASS and ignore "Module not found: Error: Can't resolve './assets/image.png'"

I'm trying to use Webpack instead of Gulp as a task runner, in this case simply compiling all SCSS files as I was doing it with Compass before. The main objectives are:
run Autoprefixer and generate separate CSS file for each SCSS that is not a partial
don't bundle images or concatenate CSS files
keep image urls as is, e.g. background-image: url(assets/image.png)
don't throw errors if images cannot be found
#1 is solved and working, however it stops working and throws an error as soon as the SCSS links to an image as in #3 above:
ERROR in ./~/css-loader!./~/postcss-loader!./~/sass-loader/lib/loader.js!./scss/style.scss
Module not found: Error: Can't resolve './assets/image.png' in 'C:\Users\robro\projects\...\my-project\dev\styles\scss
# ./~/css-loader!./~/postcss-loader!./~/sass-loader/lib/loader.js!./scss/style.scss 6:15328-15369
# ./scss/style.scss
I'd like to "simply" ignore that error and not having to copy the missing files to my local hard drive. That's mostly just me being stubborn, thinking "Compass didn't need those images to be present, why does Webpack?"
Here's my setup:
webpack.config.js
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var ExtractCSS = new ExtractTextPlugin('css/[name]');
module.exports = {
entry: {
'style.css': './scss/style.scss',
'admin.css': './scss/admin.scss'
},
output: {
filename: './css/[name]'
},
module: {
rules: [
{
test: /\.scss$/,
use: ExtractCSS.extract({
fallback: "style-loader",
use: [
"css-loader",
"postcss-loader",
"sass-loader"
]
})
},
{ test: /\.(jpg|jpeg|png|svg|gif|woff|woff2|otf|ttf)$/, use: 'ignore-loader' }
]
},
plugins: [
ExtractCSS
],
watch: true
};
package.json
{
"dependencies": {},
"devDependencies": {
"css-loader": "^0.26.1",
"extract-text-webpack-plugin": "^2.0.0-rc.3",
"ignore-loader": "^0.1.2",
"node-sass": "^4.5.0",
"postcss-loader": "^1.3.0",
"sass-loader": "^6.0.0",
"style-loader": "^0.13.1",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.3.0"
}
}
As you can see, i tried using ignore-loader to stop sass-loader from complaining about missing images, but to no avail. To be honest, I'm not even sure this is how it's intended to be used.
As soon as I remove any line that links to images from the SCSS, everything is working just fine: style.css and admin.css get built, autoprefixed and dropped into css/ folder. Now I want to keep it that way, but also use styles like background-image: url(assets/image.png) without webpack complaining about those images not being present on the file system.
Case closed: Webpack is NOT a task runner. Blog posts naming Webpack as a successor to Grunt or Gulp or fail to explicitly point out that these tools may have some overlapping features but in the end have very different goals. Grunt and Gulp are task runners and Webpack is an asset bundler. Trying to make Webpack not bundle your assets defeats it's main purpose and one's better off choosing a different tool.

Resources