我有适用于我的开发环境的scss模块,但是当我部署到生产环境时,我的样式没有被编译/应用。如何配置webpack,以使开发环境和生产环境保持一致?我知道webpack文件非常混乱,但是如果有人指出我做错了什么,我将非常感激。
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
}
],
[
'react-css-modules',
{
"filetypes": {
".scss": { "syntax": "postcss-scss" }
},
"generateScopedName": '[name]_[local]_[hash:base64:5]'
}
],
'@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: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{
test: /\.(sa|sc)ss$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: false,
localIdentName: '[name]_[local]_[hash:base64:5]'
}
},
{
loader: 'sass-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
})
]
})
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: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
},
plugins: [
new CompressionPlugin({
test: /\.(js|css|html)$/
}),
new VisualizerPlugin({
filename: '../stats/bundleStats.html'
}),
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
chunkFilename: '[id].[hash].css'
})
]
})
package.json
"scripts": {
"start": "webpack-dev-server --config webpack/webpack.dev.js --env=dev",
"start:stg": "webpack-dev-server --config webpack/webpack.dev.js --env=stg",
"start:prod": "webpack-dev-server --config webpack/webpack.dev.js --env=prod",
"build:dev": "webpack --config webpack/webpack.prod.js --env=dev",
"build:stg": "webpack --config webpack/webpack.prod.js --env=stg",
"build:prod": "webpack --config webpack/webpack.prod.js --env=prod",
"deploy:dev": "node scripts/deploy.js --env=dev",
"deploy:stg": "node scripts/deploy.js --env=stg",
"deploy:prod": "node scripts/deploy.js --env=prod",
"profile": "webpack --config webpack/webpack.profile.js --progress --profile --colors",
"profile:stats": "webpack --config webpack/webpack.profile.js --profile --json > ./stats/webpack-build-stats.json",
"formatsvg": "svgo -f ./src/images/icons --enable=inlineStyles,removeAttrs --config '{ \"plugins\": [ { \"inlineStyles\": { \"onlyMatchedOnce\": false } }, { \"removeAttrs\": { \"attrs\": \"filter\" } } ] }' --pretty",
"format": "prettier --write \"**/*.js\" prettier --write \"**/*.jsx\"",
"eslint": "eslint --quiet ./src"
},
答案 0 :(得分:1)
对于您的webpack.prod.js
文件,您需要更改此rule
:
{
test: /\.(sa|sc)ss$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: false,
localIdentName: '[name]_[local]_[hash:base64:5]'
}
},
{
loader: 'sass-loader'
}
]
},
对此:
{
test: /\.(sc|sa)ss$/,
use: [
{ loader: MiniCssExtractPlugin.loader },
{
loader: "css-loader",
options: {
modules: true,
sourceMap: false,
localIdentName: "[name]_[local]_[hash:base64:5]"
}
},
{ loader: "sass-loader" }
]
},
本质上,您需要在开发中使用style-loader
进行热重装,而在生产中,则需要使用MiniCssExtractPlugin
将所有内容编译到一个或多个CSS文件中。
您可以选择几种实现方式...
您可以简单地根据环境要求并合并所需的配置(推荐用于当前设置-您只需导出对象并进行合并):
const merge = require('webpack-merge');
const base = require('./config/webpack.base.js');
const envs = {
development: 'dev',
production: 'prod',
};
const env = envs[process.env.NODE_ENV || 'development'];
const config = require(`./config/webpack.${env}.js`);
module.exports = merge(base, config);
或者...如果要将不同的配置简化为一个配置,并根据环境有条件地使用加载程序,则可以执行以下操作:
const { NODE_ENV } = process.env;
const inDevelopment = NODE_ENV === "development";
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const cssRule = ({ exclude, modules, sourceMap, test }) => ({
test,
exclude,
use: [
inDevelopment ? "style-loader" : MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
sourceMap: sourceMap || inDevelopment,
modules: !!modules,
localIdentName: "[name]_[local]_[hash:base64:5]"
},
},
"sass-loader",
],
});
module.exports = {
mode: inDevelopment ? "development" : "production",
devServer: {
port: 3000,
contentBase: path.join(process.cwd(), 'dist/')
},
entry: [path.join(process.cwd(), 'src/main.js')],
... include other configurations
module: {
rules: [
// css imports
cssRule({ test: cssRegex, exclude: cssModuleRegex }),
// css module imports
cssRule({ test: cssModuleRegex, modules: true }),
// scss imports
cssRule({ test: sassRegex, exclude: sassModuleRegex }),
// scss module imports
cssRule({ test: sassModuleRegex, modules: true }),
...etc
]
},
... etc
}