Webpack CSS 输出总是被缩小
Webpack CSS Output Is Always Minified
对于我的特定项目,我需要控制 CSS 的缩小,并且只缩小某些文件。我非常接近使用 OptimizeCSSAssetsPlugin
的工作解决方案,我使用 assetNameRegExp
选项来选择我想要缩小的 CSS 文件。
我现在花了一段时间试图弄清楚为什么我的所有其他 CSS 文件都仍然 被缩小了。结果是 sass-loader
将 总是 在生产模式下缩小你的 CSS 无论你是否愿意。
这是我的完整 webpack.config.js
。
const CopyWebpackPlugin = require('copy-webpack-plugin');
const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries');
const FractalWebpackPlugin = require('fractal-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const path = require('path');
const PrettierPlugin = require('prettier-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = (env, argv) => {
/**
* Determine if is production mode from the command executed
*/
const isProduction = argv.mode === 'production';
/**
* Common paths
*/
const paths = {
src: 'src',
dev: 'public',
prod: 'public'
};
/**
* Generate the settings for webpack depending on if it is
* development or production mode.
*/
const settings = {
mode: isProduction ? 'production' : 'development',
outputDir: isProduction ? paths.prod : paths.dev,
fractal: {
mode: isProduction ? 'build' : 'server',
sync: isProduction ? false : true
}
};
return {
// Mode is set by --mode property in command
mode: settings.mode,
/**
* 3 entries:
* designSystem: This is Design System UI specific CSS
* website: This is website & component specific CSS
* app: This is the website & component specific JS
*/
entry: {
/**
* Main website and Design System CSS files
*/
designSystem: path.resolve(__dirname, `./${paths.src}/theme/scss/theme.scss`),
website: path.resolve(__dirname, `./${paths.src}/scss/styles.scss`),
/**
* Specific enteries for all comonents to generate a CSS file specific to that component
*/
headings: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/02-headings/headings.scss`),
paragraphs: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/03-paragraphs/paragraphs.scss`),
inlineElements: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/04-inline-elements/inline-elements.scss`),
ordered: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/05-lists/ordered/ordered.scss`),
unordered: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/05-lists/unordered/unordered.scss`),
images: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/06-images/images.scss`),
spacers: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/01-layout/02-spacers/spacers.scss`),
primaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/primary-button/primary-button.scss`),
secondaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/secondary-button/secondary-button.scss`),
tertiaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/tertiary-button/tertiary-button.scss`),
checkboxes: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/checkboxes/checkboxes.scss`),
inputs: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/inputs/inputs.scss`),
labels: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/labels/labels.scss`),
radios: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/radios/radios.scss`),
selects: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/selects/selects.scss`),
textareas: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/textareas/textareas.scss`),
footer: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/04-footer/footer.scss`),
navigation: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/05-navigation/navigation.scss`),
informationPanel: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/06-information-panel/information-panel.scss`),
informationPill: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/07-information-pill/information-pill.scss`),
modal: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/08-modal/modal.scss`),
/**
* Main website and Design System JS files
*/
app: [
'regenerator-runtime/runtime',
'core-js/modules/es6.array.from',
'core-js/modules/es6.array.for-each',
'core-js/modules/es6.object.assign',
'core-js/modules/es6.promise',
path.resolve(__dirname, `./${paths.src}/js/app.js`)
]
},
/**
* JS output goes into the scripts folder and depending on mode will
* either go into the public or the dist folder with it's chunks
*/
output: {
path: path.resolve(__dirname, `./${settings.outputDir}`),
filename: 'scripts/[name].js',
chunkFilename: 'scripts/[name].chunk.js'
},
module: {
rules: [
{
parser: {
amd: false
}
},
{
/**
* Load JS files with Babel Loader and set to transpile code to work
* in IE10 and above.
*/
test: /\.(js)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
configFile: './babel.config.js',
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'entry',
corejs: '^3.1.4',
targets: {
browsers: ['defaults, ie >= 10']
}
}
]
]
}
},
{
loader: 'eslint-loader',
options: {
configFile: '.eslintrc.json'
}
}
]
},
{
/**
* Load SASS files with 2 loaders
* PostCSS: This converts the SCSS to CSS, adds in polyfills for flexbox,
* auto prefixes and adds in normalise CSS.
* SASS Loader: This generates source maps for CSS.
*/
test: /\.(scss|sass)$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
}),
require('autoprefixer')()
],
sourceMap: true,
minimize: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: false,
outputStyle: 'uncompressed'
}
}
]
},
{
/**
* This looks for all images and uses the File Loader to move them to
* the output directory. It excludes the fonts directory so there is no
* duplication of SVG files
*/
test: /\.(png|jpg|jpeg|gif|svg)$/,
exclude: /fonts/,
use: [
{
loader: 'file-loader',
options: {
name: '[folder]/[name].[ext]',
outputPath: '/images'
}
}
]
},
{
/**
* This looks for all font files and uses the File Loader to
* move hem to the output directory. It excludes the images directory
* so there is no duplication of SVG files
*/
test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
exclude: /images/,
use: [
{
loader: 'file-loader',
options: {
name: '[folder]/[name].[ext]',
outputPath: '/fonts'
}
}
]
}
]
},
plugins: [
/**
* This prevents webpack from generating a JS file for SCSS entries
*/
new FixStyleOnlyEntriesPlugin(),
/**
* Runs SASS linting
*/
new StyleLintPlugin({
configFile: '.stylelintrc.json',
context: 'src',
files: '**/*.scss',
failOnError: false,
quiet: false,
emitErrors: true
}),
/**
* This outputs SCSS entires into CSS files and thier chunks
*/
new MiniCssExtractPlugin({
filename: 'style/[name].css',
chunkFilename: 'style/[name].chunk.css'
}),
/**
* Runs Fractal in either server mode for dev and build mode for
* production.
*/
new FractalWebpackPlugin({
mode: settings.fractal.mode,
sync: settings.fractal.sync
}),
/**
* Copies images over to the output directory
*/
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, `./${paths.src}/images`),
to: 'images'
}
]),
// new PrettierPlugin()
],
/**
* This only runs when in production mode and will minify JS and CSS
*/
optimization: {
minimize: true,
minimizer: [
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /style\/(website|designSystem).css/,
cssProcessor: require('cssnano')
}),
new TerserPlugin({
include: /\/js/,
exclude: /\/scss/
})
]
},
/**
* Generates source maps
*/
devtool: 'source-maps'
};
};
我终于弄清楚了我的问题并想 post 答案,这样如果以后有人遇到这个问题,他们可以解决它。
不管我的问题是什么,一开始我实际上并不知道是哪个加载器导致了这个问题,在做了一些研究之后我最初认为 css-loader
是罪魁祸首。我深入研究了代码,发现 css-loader
中没有缩小。下一个要研究的加载器是 sass-loader
,经过大量研究我最终发现 sass-loader
正在做缩小。查看 sass-loader
文档,我似乎没有找到任何关于缩小或如何停止它的信息。经过大量谷歌搜索后,我最终找到了记录很差的选项 outputStyle
.
据我所知,outputStyle 有 3 个选项:
outputStyle: 'compressed'
outputStyle: 'uncompressed'
outputStyle: 'expanded'
这是我的魔法选项,而 sass-loader
似乎没有注意到 webpack.config.js
中的 minimize: false
它会听取 outputStyle
选项。这将关闭所有 CSS 文件的缩小。然后,这允许 OptimizeCSSAssetsPlugin
发挥作用并缩小您需要的文件。
这里如果新sass-loader
代码:
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: false,
outputStyle: 'expanded'
}
}
这是完整的webpack.config.js
const CopyWebpackPlugin = require('copy-webpack-plugin');
const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries');
const FractalWebpackPlugin = require('fractal-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const path = require('path');
const PrettierPlugin = require('prettier-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = (env, argv) => {
/**
* Determine if is production mode from the command executed
*/
const isProduction = argv.mode === 'production';
/**
* Common paths
*/
const paths = {
src: 'src',
dev: 'public',
prod: 'public'
};
/**
* Generate the settings for webpack depending on if it is
* development or production mode.
*/
const settings = {
mode: isProduction ? 'production' : 'development',
outputDir: isProduction ? paths.prod : paths.dev,
fractal: {
mode: isProduction ? 'build' : 'server',
sync: isProduction ? false : true
}
};
return {
// Mode is set by --mode property in command
mode: settings.mode,
/**
* 3 entries:
* designSystem: This is Design System UI specific CSS
* website: This is website & component specific CSS
* app: This is the website & component specific JS
*/
entry: {
/**
* Main website and Design System CSS files
*/
designSystem: path.resolve(__dirname, `./${paths.src}/theme/scss/theme.scss`),
website: path.resolve(__dirname, `./${paths.src}/scss/styles.scss`),
/**
* Specific enteries for all comonents to generate a CSS file specific to that component
*/
headings: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/02-headings/headings.scss`),
paragraphs: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/03-paragraphs/paragraphs.scss`),
inlineElements: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/04-inline-elements/inline-elements.scss`),
ordered: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/05-lists/ordered/ordered.scss`),
unordered: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/05-lists/unordered/unordered.scss`),
images: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/06-images/images.scss`),
spacers: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/01-layout/02-spacers/spacers.scss`),
primaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/primary-button/primary-button.scss`),
secondaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/secondary-button/secondary-button.scss`),
tertiaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/tertiary-button/tertiary-button.scss`),
checkboxes: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/checkboxes/checkboxes.scss`),
inputs: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/inputs/inputs.scss`),
labels: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/labels/labels.scss`),
radios: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/radios/radios.scss`),
selects: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/selects/selects.scss`),
textareas: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/textareas/textareas.scss`),
footer: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/04-footer/footer.scss`),
navigation: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/05-navigation/navigation.scss`),
informationPanel: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/06-information-panel/information-panel.scss`),
informationPill: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/07-information-pill/information-pill.scss`),
modal: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/08-modal/modal.scss`),
/**
* Main website and Design System JS files
*/
app: [
'regenerator-runtime/runtime',
'core-js/modules/es6.array.from',
'core-js/modules/es6.array.for-each',
'core-js/modules/es6.object.assign',
'core-js/modules/es6.promise',
path.resolve(__dirname, `./${paths.src}/js/app.js`)
]
},
/**
* JS output goes into the scripts folder and depending on mode will
* either go into the public or the dist folder with it's chunks
*/
output: {
path: path.resolve(__dirname, `./${settings.outputDir}`),
filename: 'scripts/[name].js',
chunkFilename: 'scripts/[name].chunk.js'
},
module: {
rules: [
{
parser: {
amd: false
}
},
{
/**
* Load JS files with Babel Loader and set to transpile code to work
* in IE10 and above.
*/
test: /\.(js)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
configFile: './babel.config.js',
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'entry',
corejs: '^3.1.4',
targets: {
browsers: ['defaults, ie >= 10']
}
}
]
]
}
},
{
loader: 'eslint-loader',
options: {
configFile: '.eslintrc.json'
}
}
]
},
{
/**
* Load SASS files with 2 loaders
* PostCSS: This converts the SCSS to CSS, adds in polyfills for flexbox,
* auto prefixes and adds in normalise CSS.
* SASS Loader: This generates source maps for CSS.
*/
test: /\.(scss|sass)$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
}),
require('autoprefixer')()
],
sourceMap: true,
minimize: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: false,
outputStyle: 'expanded'
}
}
]
},
{
/**
* This looks for all images and uses the File Loader to move them to
* the output directory. It excludes the fonts directory so there is no
* duplication of SVG files
*/
test: /\.(png|jpg|jpeg|gif|svg)$/,
exclude: /fonts/,
use: [
{
loader: 'file-loader',
options: {
name: '[folder]/[name].[ext]',
outputPath: '/images'
}
}
]
},
{
/**
* This looks for all font files and uses the File Loader to
* move hem to the output directory. It excludes the images directory
* so there is no duplication of SVG files
*/
test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
exclude: /images/,
use: [
{
loader: 'file-loader',
options: {
name: '[folder]/[name].[ext]',
outputPath: '/fonts'
}
}
]
}
]
},
plugins: [
/**
* This prevents webpack from generating a JS file for SCSS entries
*/
new FixStyleOnlyEntriesPlugin(),
/**
* Runs SASS linting
*/
new StyleLintPlugin({
configFile: '.stylelintrc.json',
context: 'src',
files: '**/*.scss',
failOnError: false,
quiet: false,
emitErrors: true
}),
/**
* This outputs SCSS entires into CSS files and thier chunks
*/
new MiniCssExtractPlugin({
filename: 'style/[name].css',
chunkFilename: 'style/[name].chunk.css'
}),
/**
* Runs Fractal in either server mode for dev and build mode for
* production.
*/
new FractalWebpackPlugin({
mode: settings.fractal.mode,
sync: settings.fractal.sync
}),
/**
* Copies images over to the output directory
*/
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, `./${paths.src}/images`),
to: 'images'
}
]),
// new PrettierPlugin()
],
/**
* This only runs when in production mode and will minify JS and CSS
*/
optimization: {
minimize: true,
minimizer: [
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /style\/(website|designSystem).css/,
cssProcessor: require('cssnano')
}),
new TerserPlugin({
include: /\/js/,
exclude: /\/scss/
})
]
},
/**
* Generates source maps
*/
devtool: 'source-maps'
};
};
对于我的特定项目,我需要控制 CSS 的缩小,并且只缩小某些文件。我非常接近使用 OptimizeCSSAssetsPlugin
的工作解决方案,我使用 assetNameRegExp
选项来选择我想要缩小的 CSS 文件。
我现在花了一段时间试图弄清楚为什么我的所有其他 CSS 文件都仍然 被缩小了。结果是 sass-loader
将 总是 在生产模式下缩小你的 CSS 无论你是否愿意。
这是我的完整 webpack.config.js
。
const CopyWebpackPlugin = require('copy-webpack-plugin');
const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries');
const FractalWebpackPlugin = require('fractal-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const path = require('path');
const PrettierPlugin = require('prettier-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = (env, argv) => {
/**
* Determine if is production mode from the command executed
*/
const isProduction = argv.mode === 'production';
/**
* Common paths
*/
const paths = {
src: 'src',
dev: 'public',
prod: 'public'
};
/**
* Generate the settings for webpack depending on if it is
* development or production mode.
*/
const settings = {
mode: isProduction ? 'production' : 'development',
outputDir: isProduction ? paths.prod : paths.dev,
fractal: {
mode: isProduction ? 'build' : 'server',
sync: isProduction ? false : true
}
};
return {
// Mode is set by --mode property in command
mode: settings.mode,
/**
* 3 entries:
* designSystem: This is Design System UI specific CSS
* website: This is website & component specific CSS
* app: This is the website & component specific JS
*/
entry: {
/**
* Main website and Design System CSS files
*/
designSystem: path.resolve(__dirname, `./${paths.src}/theme/scss/theme.scss`),
website: path.resolve(__dirname, `./${paths.src}/scss/styles.scss`),
/**
* Specific enteries for all comonents to generate a CSS file specific to that component
*/
headings: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/02-headings/headings.scss`),
paragraphs: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/03-paragraphs/paragraphs.scss`),
inlineElements: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/04-inline-elements/inline-elements.scss`),
ordered: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/05-lists/ordered/ordered.scss`),
unordered: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/05-lists/unordered/unordered.scss`),
images: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/06-images/images.scss`),
spacers: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/01-layout/02-spacers/spacers.scss`),
primaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/primary-button/primary-button.scss`),
secondaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/secondary-button/secondary-button.scss`),
tertiaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/tertiary-button/tertiary-button.scss`),
checkboxes: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/checkboxes/checkboxes.scss`),
inputs: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/inputs/inputs.scss`),
labels: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/labels/labels.scss`),
radios: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/radios/radios.scss`),
selects: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/selects/selects.scss`),
textareas: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/textareas/textareas.scss`),
footer: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/04-footer/footer.scss`),
navigation: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/05-navigation/navigation.scss`),
informationPanel: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/06-information-panel/information-panel.scss`),
informationPill: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/07-information-pill/information-pill.scss`),
modal: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/08-modal/modal.scss`),
/**
* Main website and Design System JS files
*/
app: [
'regenerator-runtime/runtime',
'core-js/modules/es6.array.from',
'core-js/modules/es6.array.for-each',
'core-js/modules/es6.object.assign',
'core-js/modules/es6.promise',
path.resolve(__dirname, `./${paths.src}/js/app.js`)
]
},
/**
* JS output goes into the scripts folder and depending on mode will
* either go into the public or the dist folder with it's chunks
*/
output: {
path: path.resolve(__dirname, `./${settings.outputDir}`),
filename: 'scripts/[name].js',
chunkFilename: 'scripts/[name].chunk.js'
},
module: {
rules: [
{
parser: {
amd: false
}
},
{
/**
* Load JS files with Babel Loader and set to transpile code to work
* in IE10 and above.
*/
test: /\.(js)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
configFile: './babel.config.js',
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'entry',
corejs: '^3.1.4',
targets: {
browsers: ['defaults, ie >= 10']
}
}
]
]
}
},
{
loader: 'eslint-loader',
options: {
configFile: '.eslintrc.json'
}
}
]
},
{
/**
* Load SASS files with 2 loaders
* PostCSS: This converts the SCSS to CSS, adds in polyfills for flexbox,
* auto prefixes and adds in normalise CSS.
* SASS Loader: This generates source maps for CSS.
*/
test: /\.(scss|sass)$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
}),
require('autoprefixer')()
],
sourceMap: true,
minimize: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: false,
outputStyle: 'uncompressed'
}
}
]
},
{
/**
* This looks for all images and uses the File Loader to move them to
* the output directory. It excludes the fonts directory so there is no
* duplication of SVG files
*/
test: /\.(png|jpg|jpeg|gif|svg)$/,
exclude: /fonts/,
use: [
{
loader: 'file-loader',
options: {
name: '[folder]/[name].[ext]',
outputPath: '/images'
}
}
]
},
{
/**
* This looks for all font files and uses the File Loader to
* move hem to the output directory. It excludes the images directory
* so there is no duplication of SVG files
*/
test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
exclude: /images/,
use: [
{
loader: 'file-loader',
options: {
name: '[folder]/[name].[ext]',
outputPath: '/fonts'
}
}
]
}
]
},
plugins: [
/**
* This prevents webpack from generating a JS file for SCSS entries
*/
new FixStyleOnlyEntriesPlugin(),
/**
* Runs SASS linting
*/
new StyleLintPlugin({
configFile: '.stylelintrc.json',
context: 'src',
files: '**/*.scss',
failOnError: false,
quiet: false,
emitErrors: true
}),
/**
* This outputs SCSS entires into CSS files and thier chunks
*/
new MiniCssExtractPlugin({
filename: 'style/[name].css',
chunkFilename: 'style/[name].chunk.css'
}),
/**
* Runs Fractal in either server mode for dev and build mode for
* production.
*/
new FractalWebpackPlugin({
mode: settings.fractal.mode,
sync: settings.fractal.sync
}),
/**
* Copies images over to the output directory
*/
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, `./${paths.src}/images`),
to: 'images'
}
]),
// new PrettierPlugin()
],
/**
* This only runs when in production mode and will minify JS and CSS
*/
optimization: {
minimize: true,
minimizer: [
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /style\/(website|designSystem).css/,
cssProcessor: require('cssnano')
}),
new TerserPlugin({
include: /\/js/,
exclude: /\/scss/
})
]
},
/**
* Generates source maps
*/
devtool: 'source-maps'
};
};
我终于弄清楚了我的问题并想 post 答案,这样如果以后有人遇到这个问题,他们可以解决它。
不管我的问题是什么,一开始我实际上并不知道是哪个加载器导致了这个问题,在做了一些研究之后我最初认为 css-loader
是罪魁祸首。我深入研究了代码,发现 css-loader
中没有缩小。下一个要研究的加载器是 sass-loader
,经过大量研究我最终发现 sass-loader
正在做缩小。查看 sass-loader
文档,我似乎没有找到任何关于缩小或如何停止它的信息。经过大量谷歌搜索后,我最终找到了记录很差的选项 outputStyle
.
据我所知,outputStyle 有 3 个选项:
outputStyle: 'compressed'
outputStyle: 'uncompressed'
outputStyle: 'expanded'
这是我的魔法选项,而 sass-loader
似乎没有注意到 webpack.config.js
中的 minimize: false
它会听取 outputStyle
选项。这将关闭所有 CSS 文件的缩小。然后,这允许 OptimizeCSSAssetsPlugin
发挥作用并缩小您需要的文件。
这里如果新sass-loader
代码:
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: false,
outputStyle: 'expanded'
}
}
这是完整的webpack.config.js
const CopyWebpackPlugin = require('copy-webpack-plugin');
const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries');
const FractalWebpackPlugin = require('fractal-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const path = require('path');
const PrettierPlugin = require('prettier-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = (env, argv) => {
/**
* Determine if is production mode from the command executed
*/
const isProduction = argv.mode === 'production';
/**
* Common paths
*/
const paths = {
src: 'src',
dev: 'public',
prod: 'public'
};
/**
* Generate the settings for webpack depending on if it is
* development or production mode.
*/
const settings = {
mode: isProduction ? 'production' : 'development',
outputDir: isProduction ? paths.prod : paths.dev,
fractal: {
mode: isProduction ? 'build' : 'server',
sync: isProduction ? false : true
}
};
return {
// Mode is set by --mode property in command
mode: settings.mode,
/**
* 3 entries:
* designSystem: This is Design System UI specific CSS
* website: This is website & component specific CSS
* app: This is the website & component specific JS
*/
entry: {
/**
* Main website and Design System CSS files
*/
designSystem: path.resolve(__dirname, `./${paths.src}/theme/scss/theme.scss`),
website: path.resolve(__dirname, `./${paths.src}/scss/styles.scss`),
/**
* Specific enteries for all comonents to generate a CSS file specific to that component
*/
headings: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/02-headings/headings.scss`),
paragraphs: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/03-paragraphs/paragraphs.scss`),
inlineElements: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/04-inline-elements/inline-elements.scss`),
ordered: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/05-lists/ordered/ordered.scss`),
unordered: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/03-typography/05-lists/unordered/unordered.scss`),
images: path.resolve(__dirname, `./${paths.src}/patterns/01-branding/06-images/images.scss`),
spacers: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/01-layout/02-spacers/spacers.scss`),
primaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/primary-button/primary-button.scss`),
secondaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/secondary-button/secondary-button.scss`),
tertiaryButton: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/02-buttons/tertiary-button/tertiary-button.scss`),
checkboxes: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/checkboxes/checkboxes.scss`),
inputs: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/inputs/inputs.scss`),
labels: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/labels/labels.scss`),
radios: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/radios/radios.scss`),
selects: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/selects/selects.scss`),
textareas: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/03-form-elements/textareas/textareas.scss`),
footer: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/04-footer/footer.scss`),
navigation: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/05-navigation/navigation.scss`),
informationPanel: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/06-information-panel/information-panel.scss`),
informationPill: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/07-information-pill/information-pill.scss`),
modal: path.resolve(__dirname, `./${paths.src}/patterns/02-ui-components/08-modal/modal.scss`),
/**
* Main website and Design System JS files
*/
app: [
'regenerator-runtime/runtime',
'core-js/modules/es6.array.from',
'core-js/modules/es6.array.for-each',
'core-js/modules/es6.object.assign',
'core-js/modules/es6.promise',
path.resolve(__dirname, `./${paths.src}/js/app.js`)
]
},
/**
* JS output goes into the scripts folder and depending on mode will
* either go into the public or the dist folder with it's chunks
*/
output: {
path: path.resolve(__dirname, `./${settings.outputDir}`),
filename: 'scripts/[name].js',
chunkFilename: 'scripts/[name].chunk.js'
},
module: {
rules: [
{
parser: {
amd: false
}
},
{
/**
* Load JS files with Babel Loader and set to transpile code to work
* in IE10 and above.
*/
test: /\.(js)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
configFile: './babel.config.js',
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'entry',
corejs: '^3.1.4',
targets: {
browsers: ['defaults, ie >= 10']
}
}
]
]
}
},
{
loader: 'eslint-loader',
options: {
configFile: '.eslintrc.json'
}
}
]
},
{
/**
* Load SASS files with 2 loaders
* PostCSS: This converts the SCSS to CSS, adds in polyfills for flexbox,
* auto prefixes and adds in normalise CSS.
* SASS Loader: This generates source maps for CSS.
*/
test: /\.(scss|sass)$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
}),
require('autoprefixer')()
],
sourceMap: true,
minimize: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: false,
outputStyle: 'expanded'
}
}
]
},
{
/**
* This looks for all images and uses the File Loader to move them to
* the output directory. It excludes the fonts directory so there is no
* duplication of SVG files
*/
test: /\.(png|jpg|jpeg|gif|svg)$/,
exclude: /fonts/,
use: [
{
loader: 'file-loader',
options: {
name: '[folder]/[name].[ext]',
outputPath: '/images'
}
}
]
},
{
/**
* This looks for all font files and uses the File Loader to
* move hem to the output directory. It excludes the images directory
* so there is no duplication of SVG files
*/
test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
exclude: /images/,
use: [
{
loader: 'file-loader',
options: {
name: '[folder]/[name].[ext]',
outputPath: '/fonts'
}
}
]
}
]
},
plugins: [
/**
* This prevents webpack from generating a JS file for SCSS entries
*/
new FixStyleOnlyEntriesPlugin(),
/**
* Runs SASS linting
*/
new StyleLintPlugin({
configFile: '.stylelintrc.json',
context: 'src',
files: '**/*.scss',
failOnError: false,
quiet: false,
emitErrors: true
}),
/**
* This outputs SCSS entires into CSS files and thier chunks
*/
new MiniCssExtractPlugin({
filename: 'style/[name].css',
chunkFilename: 'style/[name].chunk.css'
}),
/**
* Runs Fractal in either server mode for dev and build mode for
* production.
*/
new FractalWebpackPlugin({
mode: settings.fractal.mode,
sync: settings.fractal.sync
}),
/**
* Copies images over to the output directory
*/
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, `./${paths.src}/images`),
to: 'images'
}
]),
// new PrettierPlugin()
],
/**
* This only runs when in production mode and will minify JS and CSS
*/
optimization: {
minimize: true,
minimizer: [
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /style\/(website|designSystem).css/,
cssProcessor: require('cssnano')
}),
new TerserPlugin({
include: /\/js/,
exclude: /\/scss/
})
]
},
/**
* Generates source maps
*/
devtool: 'source-maps'
};
};