Webpack - scss/css 模块样式未在产品中应用
Posted
技术标签:
【中文标题】Webpack - scss/css 模块样式未在产品中应用【英文标题】:Webpack - scss/css modules styles not being applied in prod 【发布时间】:2020-03-27 15:16:21 【问题描述】:我正在使用 scss 模块,所以我在我的 react 组件中使用了 styleName
,并且一切都在 dev
中运行。 prod
中的元素看起来像 <div class="row" stylename="table"></div>
,但没有对 table
应用任何样式。
webpack 配置被分成多个文件(webpack.profile.js
、webpack.base.js
、webpack.dev.js
、webpack.prod.js
)
旁注:我还注意到某些 jenkins 作业无法处理 @
变量,不确定它是否与 webpack/sass-loader 有关。
webpack.profile.js
const path = require('path')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CompressionPlugin = require('compression-webpack-plugin')
const VisualizerPlugin = require('webpack-visualizer-plugin')
module.exports = require('./webpack.base')(
mode: 'production',
devServer:
port: 3000,
contentBase: path.join(process.cwd(), 'dist/')
,
optimization:
minimizer: [
new UglifyJsPlugin(
cache: true,
parallel: true
),
new OptimizeCSSAssetsPlugin()
]
,
module:
rules: [
test: /\.(sc|sa|c)ss$/,
use: [
loader: MiniCssExtractPlugin.loader ,
loader: "css-loader",
options:
modules: true,
sourceMap: true,
localIdentName: "[name]_[local]_[hash:base64:5]"
]
]
,
plugins: [
new CompressionPlugin(
test: /\.(js|css|html)$/
),
new VisualizerPlugin(
filename: '../stats/bundleStats.html'
),
new MiniCssExtractPlugin(
filename: '[name].[hash].css',
chunkFilename: '[id].[hash].css'
)
]
)
webpack.base.js
const path = require('path')
const Dotenv = require('dotenv-webpack')
const HtmlWebPackPlugin = require('html-webpack-plugin')
module.exports = options =>
let envPath = '.env'
process.argv.forEach(val =>
if (val.includes('--env='))
const curEnv = val.slice(6)
if (['dev', 'stg'].includes(curEnv))
envPath = `.env.$curEnv`
)
return
mode: options.mode,
devServer: options.devServer,
entry: [path.join(process.cwd(), 'src/main.js')],
output:
path: path.join(__dirname, '../dist/'),
publicPath: '/',
filename: '[name].[hash].js',
chunkFilename: '[id].[hash].js'
,
resolve:
extensions: ['.js', '.jsx'],
modules: [
path.join(__dirname, '../src'),
path.join(__dirname, '../node_modules')
],
alias:
'@constants': path.join(__dirname, '../src/constants'),
'@c': path.join(__dirname, '../src/components'),
'@C': path.join(__dirname, '../src/containers')
,
plugins: options.plugins.concat([
new Dotenv(
path: path.join(process.cwd(), envPath)
),
new HtmlWebPackPlugin(
inject: true,
template: path.join(__dirname, '../src/static/index.html'),
favicon: path.join(__dirname, '../src/static/favicon.ico')
)
]),
module:
rules: options.module.rules.concat([
//
// enforce: 'pre',
// test: /\.jsx?$/,
// exclude: /node_modules/,
// use: [
//
// loader: 'eslint-loader',
// options:
// quiet: true
//
//
// ]
// ,
test: /\.(woff|woff2|eot|ttf|otf)$/,
exclude: [ /\.scss$/ ],
use: [
loader: 'file-loader',
options:
name: '[hash].[ext]',
outputPath: 'fonts'
]
,
test: /\.svg$/,
loader: 'svg-react-loader'
,
test: /\.(gif|png|jpe?g)$/i,
use: [
loader: 'url-loader',
options:
limit: 10 * 1024,
name: '[hash].[ext]',
outputPath: 'assets'
,
loader: 'image-webpack-loader',
options:
disable: options.mode === 'development'
]
])
webpack.dev.js
const webpack = require('webpack')
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
module.exports = require('./webpack.base')(
mode: 'development',
devServer:
hot: true,
port: 3000,
historyApiFallback: true
,
plugins: [
new webpack.HotModuleReplacementPlugin(),
new BrowserSyncPlugin(
proxy: 'http://localhost:3000/', open: false ,
reload: false
)
],
module:
rules: [
test: /\.jsx?$/,
exclude: /node_modules/,
use:
loader: 'babel-loader',
options:
plugins: [
[
'react-css-modules',
"filetypes":
".scss": "syntax": "postcss-scss"
,
"generateScopedName": '[name]_[local]_[hash:base64:5]'
],
],
,
,
resolve:
extensions: ['.js', '.jsx']
,
test: /\.(sa|sc)ss$/,
use: [
loader: 'style-loader' ,
loader: 'css-loader',
options:
modules: true,
sourceMap: true,
localIdentName: '[name]_[local]_[hash:base64:5]'
,
loader: 'sass-loader'
]
,
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
,
]
)
webpack.prod.js
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = require('./webpack.base')(
mode: 'production',
devServer:
port: 3000,
contentBase: path.join(process.cwd(), 'dist/')
,
optimization:
minimize: true,
minimizer: [
new TerserPlugin(
cache: true,
parallel: true
),
new OptimizeCSSAssetsPlugin()
]
,
module:
rules: [
test: /\.jsx?$/,
exclude: /node_modules\/@babel/,
use:
loader: 'babel-loader',
options:
presets: [
[
'@babel/preset-env',
'targets':
'ie': '11'
,
'loose': true,
'forceAllTransforms': true
],
'@babel/preset-react'
],
sourceType: 'unambiguous',
plugins: [
[
'@babel/plugin-proposal-decorators',
'legacy': true
],
'@babel/plugin-transform-runtime',
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-function-bind',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-export-default-from',
'@babel/plugin-proposal-export-namespace-from'
]
,
resolve:
extensions: ['.js', '.jsx']
,
test: /\.(sc|sa)ss$/,
use: [
loader: MiniCssExtractPlugin.loader ,
loader: "css-loader",
options:
modules: true,
sourceMap: true,
localIdentName: "[name]_[local]_[hash:base64:5]"
,
loader: "postcss-loader" ,
loader: "sass-loader"
]
,
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
]
,
plugins: [
new CleanWebpackPlugin([path.join(process.cwd(), '/dist')],
allowExternal: true
),
new MiniCssExtractPlugin(
filename: '[name].[hash].css',
chunkFilename: '[id].[hash].css'
),
new CompressionPlugin(
test: /\.(js|css)$/,
filename: asset => asset.file
)
]
)
【问题讨论】:
【参考方案1】:对于这行代码
test: /\.(sc|sa|c)ss$/,
use: [
loader: MiniCssExtractPlugin.loader ,
loader: "css-loader",
我很确定你不能这样做,因为 scss 和 sass 需要有 sass 或 scss 加载器,所以如果你使用 css-loader,它就无法处理 sass 或 scss
这是我的配置方式
module:
rules: [
test: /\.scss$/,
use: [
'style-loader',
MiniCssExtractPlugin.loader,
loader: "css-loader",
options:
minimize: true,
sourceMap: true
,
loader: "sass-loader"
]
]
你可以查看我的完整配置here
【讨论】:
我正在尝试使用 scss 模块并生成一个作用域名称,其中类名看起来像table_3A5D
。我的元素的类名/样式名正在转换,所以我不确定是否是未加载 scss 样式表,或者转换样式名是否可以解决问题。
我已经通过将react-css-modules
插件添加到babel-loader
来处理scss 文件类型来解决我的问题。以上是关于Webpack - scss/css 模块样式未在产品中应用的主要内容,如果未能解决你的问题,请参考以下文章