能否通过Webpack提取Sass而不编译为CSS?
Hey Andy, I’ve been in a similar spot before—trying to get Webpack to spit out both the JS bundle and raw SCSS files for external processing can be tricky if you’re using the wrong tools. Let’s break down why your initial approach didn’t work, then walk through two solid solutions.
First, quick note: ExtractTextWebpackPlugin (which is actually deprecated now, replaced by mini-css-extract-plugin) is designed to pull compiled CSS out of your bundle. Since you want the uncompiled SCSS (with variable overrides), that plugin isn’t the right fit here—that’s why your raw-loader combo failed.
Let’s start with the simplest solution, then move to a more flexible one for multiple variable versions.
Solution 1: Use raw-loader + file-loader to Output Raw SCSS
This setup will let Webpack read your SCSS files as plain text and output them directly to your dist folder alongside your JS bundle.
Step 1: Install Required Loaders
First, install the loaders you need:
npm install raw-loader file-loader --save-dev
Step 2: Update Webpack Config
Add a rule to handle your SCSS files specifically for raw output. Here’s a simplified config example:
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ // Your existing JS processing rule (e.g., Babel) { test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' }, // Rule to output raw SCSS { test: /\.scss$/, include: path.resolve(__dirname, 'src/styles'), // Target your SCSS source folder use: [ { loader: 'file-loader', options: { name: 'bundle.scss' // Name of the output SCSS file } }, 'raw-loader' // Reads the SCSS as plain text ] } ] } };
When you run webpack, this will output both dist/bundle.js and dist/bundle.scss—the SCSS will be exactly your source file, ready for external compilation.
Solution 2: Generate Multiple SCSS Versions with Custom Variables
If you need multiple SCSS files with different variable values (e.g., theme variants), you can either use Webpack’s multi-compiler mode or a custom plugin. Let’s go with the custom plugin approach because it’s cleaner for variable overrides.
Step 1: Create a Custom Webpack Plugin
This plugin will hook into Webpack’s emit process, read your base SCSS file, replace variables, and output the modified SCSS file.
const path = require('path'); const fs = require('fs'); class GenerateThemedSCSSPlugin { constructor({ outputFilename, variables }) { this.outputFilename = outputFilename; this.variables = variables; } apply(compiler) { // Hook into the emit phase (right before files are written to disk) compiler.hooks.emit.tapAsync('GenerateThemedSCSSPlugin', (compilation, callback) => { // Read your base SCSS file const baseSCSSPath = path.resolve(__dirname, 'src/styles/main.scss'); let scssContent = fs.readFileSync(baseSCSSPath, 'utf8'); // Replace each variable in the SCSS content Object.entries(this.variables).forEach(([varName, varValue]) => { const regex = new RegExp(`\\$${varName}:\\s*.+?;`, 'g'); scssContent = scssContent.replace(regex, `$${varName}: ${varValue};`); }); // Add the modified SCSS to the compilation assets compilation.assets[this.outputFilename] = { source: () => scssContent, size: () => scssContent.length }; callback(); }); } } module.exports = GenerateThemedSCSSPlugin;
Step 2: Use the Plugin in Your Webpack Config
Now import and use the plugin to generate as many themed SCSS files as you need:
const path = require('path'); const GenerateThemedSCSSPlugin = require('./GenerateThemedSCSSPlugin'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ // Your JS processing rule here { test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' } ] }, plugins: [ // Generate a red-themed SCSS new GenerateThemedSCSSPlugin({ outputFilename: 'bundle-red.scss', variables: { 'primary-color': '#ff0000', 'button-radius': '8px' } }), // Generate a blue-themed SCSS new GenerateThemedSCSSPlugin({ outputFilename: 'bundle-blue.scss', variables: { 'primary-color': '#0066ff', 'button-radius': '4px' } }) ] };
Now when you run webpack, you’ll get bundle.js, bundle-red.scss, and bundle-blue.scss in your dist folder—each with the variable values you specified.
Key Takeaways
- Avoid ExtractTextWebpackPlugin/mini-css-extract-plugin for this use case—they’re for compiled CSS, not raw SCSS.
- raw-loader + file-loader is perfect if you just need a single raw SCSS file.
- Custom plugins give you full control for multiple themed/variable versions.
Either approach will let you keep your Webpack JS bundle intact while generating the SCSS files you need for external processing with lib-sass.
内容的提问来源于stack exchange,提问作者AndyPerlitch

