ΠΊΠ°ΠΊΠΈΠ΅-Π½ΠΈΠ±ΡΠ΄Ρ Π½ΠΎΠ²ΠΎΡΡΠΈ ΠΎΠ± ΡΡΠΎΠΌ ΡΠΆΠ΅ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠΎΠ²Π°Π½Ρ?
Π― ΡΠ΄Π΅Π»Π°Π» ΡΡΠΎ Π² razzle.config.js
"use strict";
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
modify: (config, { target, dev }, webpack) => {
const appConfig = Object.assign({}, config);
// Setup SCSS
if (target === "web") {
appConfig.module.rules.push(
{
test: /\.(sa|sc|c)ss$/,
use: [
dev ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
]
}
);
}
else {
// On the server, we can just simply use css-loader to
// deal with scss imports
appConfig.module.rules.push({
test: /\.(sa|sc|c)ss$/,
use: "css-loader"
});
}
return appConfig;
}
};
ΠΠ°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ²:
"devDependencies": {
"css-loader": "^1.0.0",
"mini-css-extract-plugin": "^0.4.1",
"node-sass": "^4.9.2",
"razzle": "^2.4.0",
"sass-loader": "^7.1.0"
}
ΠΡΠΈΠ²Π΅Ρ! ΠΡΠ°ΠΊ, Π²ΠΎΡ ΡΠ΄Π΅Π»ΠΊΠ° ΠΌΠ΅ΠΆΠ΄Ρ ΠΎΡΠΊΡΡΡΡΠΌ ΠΈΡΡ ΠΎΠ΄Π½ΡΠΌ ΠΊΠΎΠ΄ΠΎΠΌ ΠΈ ΠΌΠΎΠ΅ΠΉ ΠΏΠΎΠ²ΡΠ΅Π΄Π½Π΅Π²Π½ΠΎΠΉ ΡΠ°Π±ΠΎΡΠΎΠΉ ΠΈ ΠΆΠΈΠ·Π½ΡΡ, Π° ΡΠ°ΠΊΠΆΠ΅ ΡΠ΅ΠΌ, ΡΡΠΎ Π½Π΅Ρ, ΠΌΠ½Π΅ Π΅ΡΡΡ ΡΠ΅ΠΌ ΡΠΏΡΠ°Π²Π»ΡΡΡ, ΠΏΠΎΡΡΠΎΠΌΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ Π±ΠΎΡΠ° GitHub Π΄Π»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·Π°ΡΠΈΠΈ Π½Π΅ΠΊΠΎΡΠΎΡΡΡ Π²Π΅ΡΠ΅ΠΉ Π·Π΄Π΅ΡΡ ΠΈ ΡΠ°ΠΌ. ΠΡΠΎΡ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠΉ Π±ΠΎΡ GitHub Π±ΡΠ΄Π΅Ρ ΠΎΡΠΌΠ΅ΡΠ°ΡΡ Π΅Π³ΠΎ ΠΊΠ°ΠΊ ΡΡΡΠ°ΡΠ΅Π²ΡΠΈΠΉ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ Π² ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π΅ Π²ΡΠ΅ΠΌΡ Π² Π½Π΅ΠΌ Π½Π΅ Π±ΡΠ»ΠΎ Π°ΠΊΡΠΈΠ²Π½ΠΎΡΡΠΈ. ΠΠ½ Π±ΡΠ΄Π΅Ρ Π·Π°ΠΊΡΡΡ, Π΅ΡΠ»ΠΈ Π² ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ Π΄Π½Π΅ΠΉ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π½ΠΈΠΊΠ°ΠΊΠΎΠΉ Π°ΠΊΡΠΈΠ²Π½ΠΎΡΡΠΈ. ΠΠ΅ ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΠΉΡΠ΅ ΡΡΠΎ Π½Π° ΡΠ²ΠΎΠΉ ΡΡΠ΅Ρ - ΡΠ΅ΡΡΠ΅Π·Π½ΠΎ - ΡΡΠΎ ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅. ΠΡΠ»ΠΈ ΡΡΠΎ ΠΎΡΠΈΠ±ΠΊΠ°, ΠΏΡΠΎΡΡΠΎ ΠΎΡΡΠ°Π²ΡΡΠ΅ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ, ΠΎΡΠΏΡΠ°Π²ΡΡΠ΅ ΠΌΠ½Π΅ DM, ΠΎΡΠΏΡΠ°Π²ΡΡΠ΅ ΠΊΡΡΡΠ΅ΡΠ° ΠΈΠ»ΠΈ Π΄ΡΠΌΠΎΠ²ΠΎΠΉ ΡΠΈΠ³Π½Π°Π».
@jaredpalmer ΠΠ΅ ΠΌΠΎΠ³Π»ΠΈ Π±Ρ Π²Ρ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΡΡΠ»ΡΠΊ Π₯Π°ΠΊΡΠΎΠ±Π΅ΡΡΠ΅ΡΡΠ°?
ΠΠ³Π°
ΠΠΎΠ±ΡΡΠΉ ΠΠ΄Π°
ΠΠΎΠ½Π΅ΡΠ½ΠΎ, ΡΡΠΎ ΡΡ ΠΈΠΌΠ΅Π΅ΡΡ Π² Π²ΠΈΠ΄Ρ ΠΏΠΎΠ΄ ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠΌ? ΠΠ°ΠΊ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½ΡΠ΅ ΠΏΠ»Π°Π³ΠΈΠ½Ρ?
Π ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π΅ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² Π΅ΡΡΡ ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½ΡΠ΅ ΠΏΠ»Π°Π³ΠΈΠ½Ρ. ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΡΠ²ΠΈΠ΄Π΅ΡΡ ΡΠ°ΠΌ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠ².
ΠΠΎΠ΄Π΅Π»ΡΡΡ ΠΈ ΡΠ²ΠΎΠ΅ΠΉ Π²Π΅ΡΡΠΈΠ΅ΠΉ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ ΡΠΎ scss, ΠΌΠΎΠΆΠ΅Ρ, ΠΊΠΎΠΌΡ-ΡΠΎ ΠΏΡΠΈΠ³ΠΎΠ΄ΠΈΡΡΡ.
Π― ΠΏΠΎΠ΄ΡΠΌΠ°Π», ΡΡΠΎ ΠΌΠ½Π΅ Π½Π΅ Π½ΡΠΆΠ½ΠΎ ΠΏΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡ ΠΏΡΠ°Π²ΠΈΠ»Π° css Π΄Π»Ρ scss, ΠΏΠΎΡΡΠΎΠΌΡ Ρ ΠΏΡΠΎΡΡΠΎ Π΄Π΅Π»Π°Ρ ΠΊΠΎΠΏΠΈΡ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π° ΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡ Π·Π°Π³ΡΡΠ·ΡΠΈΠΊ scss.
'use strict';
const makeLoaderFinder = require('razzle-dev-utils/makeLoaderFinder');
const paths = require('razzle/config/paths');
const cssLoaderFinder = makeLoaderFinder('css-loader');
module.exports = {
modify(baseConfig, {dev}, webpack) {
/* make a copy of config */
const config = Object.assign({}, baseConfig);
const scssLoader = {
loader: require.resolve('sass-loader'),
options: {
sourceMap: dev,
},
};
// Copy base css rules and add scss support
config.module.rules.filter(cssLoaderFinder).forEach(rule => {
const isCssModuleRule = !rule.test.test('module.css');
const scssExclude = [paths.appBuild];
let scssTest = /\.s[ac]ss$/;
if (isCssModuleRule) {
scssTest = /\.module\.s[ac]ss$/;
} else {
scssExclude.push(/\.module\.s[ac]ss$/);
}
// Use default configs
config.module.rules.push({
test: scssTest,
exclude: scssExclude,
use: [
...rule.use,
scssLoader,
]
});
});
// adding ./src to module resolver so I can import modules with absolute paths
config.resolve.modules.push('./src');
return config;
},
};
ΠΠΎΠ΄Π΅Π»ΡΡΡ ΠΈ ΡΠ²ΠΎΠ΅ΠΉ Π²Π΅ΡΡΠΈΠ΅ΠΉ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ ΡΠΎ scss, ΠΌΠΎΠΆΠ΅Ρ, ΠΊΠΎΠΌΡ-ΡΠΎ ΠΏΡΠΈΠ³ΠΎΠ΄ΠΈΡΡΡ.
Π― ΠΏΠΎΠ΄ΡΠΌΠ°Π», ΡΡΠΎ ΠΌΠ½Π΅ Π½Π΅ Π½ΡΠΆΠ½ΠΎ ΠΏΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡ ΠΏΡΠ°Π²ΠΈΠ»Π° css Π΄Π»Ρ scss, ΠΏΠΎΡΡΠΎΠΌΡ Ρ ΠΏΡΠΎΡΡΠΎ Π΄Π΅Π»Π°Ρ ΠΊΠΎΠΏΠΈΡ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»Π° ΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡ Π·Π°Π³ΡΡΠ·ΡΠΈΠΊ scss.
'use strict'; const makeLoaderFinder = require('razzle-dev-utils/makeLoaderFinder'); const paths = require('razzle/config/paths'); const cssLoaderFinder = makeLoaderFinder('css-loader'); module.exports = { modify(baseConfig, {dev}, webpack) { /* make a copy of config */ const config = Object.assign({}, baseConfig); const scssLoader = { loader: require.resolve('sass-loader'), options: { sourceMap: dev, }, }; // Copy base css rules and add scss support config.module.rules.filter(cssLoaderFinder).forEach(rule => { const isCssModuleRule = !rule.test.test('module.css'); const scssExclude = [paths.appBuild]; let scssTest = /\.s[ac]ss$/; if (isCssModuleRule) { scssTest = /\.module\.s[ac]ss$/; } else { scssExclude.push(/\.module\.s[ac]ss$/); } // Use default configs config.module.rules.push({ test: scssTest, exclude: scssExclude, use: [ ...rule.use, scssLoader, ] }); }); // adding ./src to module resolver so I can import modules with absolute paths config.resolve.modules.push('./src'); return config; }, };
ΠΡΠΈΠ²Π΅Ρ, ΠΏΠΎΠΆΠ°Π»ΡΠΉΡΡΠ°, ΠΊΠ°ΠΊΠΈΠ΅ devDependencies ΠΌΠ½Π΅ ΠΏΠΎΠ½Π°Π΄ΠΎΠ±ΡΡΡΡ, ΡΡΠΎΠ±Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ Π²Π°ΡΠ΅Π³ΠΎ razzle ?. ΡΡ Π½Π΅ ΡΠΏΠΎΠΌΡΠ½ΡΠ» ΠΈΡ
@Toyurc Π― ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π» [email protected]
ΠΈ [email protected]
.
ΠΡΠΈΠ²Π΅Ρ, Π΅ΡΡΡ Π»ΠΈ ΠΊΠ°ΠΊΠΎΠ΅-Π½ΠΈΠ±ΡΠ΄Ρ Π±ΡΡΡΡΠΎΠ΅ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅, ΡΡΠΎΠ±Ρ ΠΌΠ΅Π½ΡΡΠ΅ ΡΠΈΡΠ°ΡΡ?
Ρ ΠΏΠΎΠ»ΡΡΠΈΠ»
Module parse failed: Unexpected character '@' (1:0)
You may need an appropriate loader to handle this file type.
> <strong i="7">@import</strong>
Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎ ΠΎΡ ΡΠΎΠ³ΠΎ, ΡΡΠΎ Ρ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Ρ ΠΈ Ρ. Π΄.
ΠΡΠΈΠ²Π΅Ρ, Π΅ΡΡΡ Π»ΠΈ ΠΊΠ°ΠΊΠΎΠ΅-Π½ΠΈΠ±ΡΠ΄Ρ Π±ΡΡΡΡΠΎΠ΅ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅, ΡΡΠΎΠ±Ρ ΠΌΠ΅Π½ΡΡΠ΅ ΡΠΈΡΠ°ΡΡ?
Ρ ΠΏΠΎΠ»ΡΡΠΈΠ»Module parse failed: Unexpected character '@' (1:0) You may need an appropriate loader to handle this file type. > <strong i="8">@import</strong>
Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎ ΠΎΡ ΡΠΎΠ³ΠΎ, ΡΡΠΎ Ρ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Ρ ΠΈ Ρ. Π΄.
ΠΠ»Ρ .less
config ΠΌΠΎΠΆΠ΅Ρ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ ΡΠ°ΠΊ. Π― Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π» ΠΌΠ΅Π½ΡΡΠ΅, ΡΠΎΠ»ΡΠΊΠΎ Π΄Π΅ΡΠ·ΠΎΡΡΡ, Π½ΠΎ ΠΎΠ±ΡΠΈΠ΅ ΠΏΡΠ°Π²ΠΈΠ»Π° Π²ΡΠ΅ ΡΠ°Π²Π½ΠΎ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΏΡΠΈΠΌΠ΅Π½ΡΡΡΡΡ.
'use strict';
const makeLoaderFinder = require('razzle-dev-utils/makeLoaderFinder');
const paths = require('razzle/config/paths');
const cssLoaderFinder = makeLoaderFinder('css-loader');
module.exports = {
modify(baseConfig, {dev}, webpack) {
/* make a copy of config */
const config = Object.assign({}, baseConfig);
const lessLoader = {
loader: require.resolve('less-loader'),
options: {
sourceMap: dev,
},
};
// Copy base css rules and add less support
config.module.rules.filter(cssLoaderFinder).forEach(rule => {
const isCssModuleRule = !rule.test.test('module.css');
const lessExclude = [paths.appBuild];
let lessTest = /\.less$/;
if (isCssModuleRule) {
lessTest = /\.module\.less$/;
} else {
lessExclude.push(/\.module\.less$/);
}
// Use default configs
config.module.rules.push({
test: lessTest,
exclude: lessExclude,
use: [
...rule.use,
lessLoader,
]
});
});
// adding ./src to module resolver so I can import modules with absolute paths
config.resolve.modules.push('./src');
return config;
},
};
ΠΠ΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ less-loader
ΠΈ less
.
Π― ΠΏΡΠΎΡΡΠΎ ΠΏΡΠΎΡΠΌΠ°ΡΡΠΈΠ²Π°Ρ Π½Π΅ΠΊΠΎΡΠΎΡΡΠ΅ ΡΡΠ°ΡΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ, ΡΠ²ΡΠ·Π°Π½Π½ΡΠ΅ Ρ scss, ΠΊΠΎΡΠΎΡΡΠ΅, ΠΊΠ°ΠΊ ΠΌΠ½Π΅ ΠΊΠ°ΠΆΠ΅ΡΡΡ, ΡΠ΅ΠΏΠ΅ΡΡ ΡΠ΅ΡΠ΅Π½Ρ. ΠΠ΅ ΠΏΠΎΡ ΠΎΠΆΠ΅, ΡΡΠΎ ΡΠ΅ΠΉΡΠ°Ρ ΠΌΠ΅Π½ΡΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ², Π½ΠΎ ΡΠ΅ΠΏΠ΅ΡΡ Π΅ΡΡΡ ΠΏΠ»Π°Π³ΠΈΠ½ scss, fyi.
ΠΠ°ΠΊΠ΅Ρ scss ΡΠ΅ΠΏΠ΅ΡΡ ΠΎΠΏΡΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½ Π·Π΄Π΅ΡΡ ΠΈ ΠΎΡΠ»ΠΈΡΠ½ΠΎ ΠΌΠ½Π΅ ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ΠΈΡ.
https://www.npmjs.com/package/razzle-plugin-scss
Π‘ΠΌ. ΠΡΠΈΠΌΠ΅Ρ Π·Π΄Π΅ΡΡ:
https://github.com/jaredpalmer/razzle/tree/master/examples/with-scss
ΠΠ±Π° Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ Π² ΡΠ»Π΅Π΄ΡΡΡΡΡ Π²Π΅ΡΠΊΡ, Π·Π°ΠΊΡΡΠ²Π°Ρ
Π‘Π°ΠΌΡΠΉ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ
Π― ΡΠ΄Π΅Π»Π°Π» ΡΡΠΎ Π² razzle.config.js
ΠΠ°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ²: