luk*_*ine 8 css optimization bundling-and-minification webpack css-loader
对于我的特定项目,我需要控制 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'
};
};
Run Code Online (Sandbox Code Playgroud)
luk*_*ine 14
我终于找到了我的问题并想发布答案,以便将来如果其他人遇到这个问题,他们可以解决它。
尽管我的问题是这样说的,但一开始我实际上并不知道是哪个装载机导致了这个问题,在做了一些研究之后,我最初认为css-loader
是罪魁祸首。我对代码进行了一些挖掘,发现css-loader
. 下一个要研究的加载器是sass-loader
,经过大量研究,我最终发现sass-loader
是在进行缩小。查看sass-loader
文档我似乎没有找到任何关于缩小或如何阻止它的信息。经过大量的谷歌搜索,我最终找到了记录非常糟糕的选项outputStyle
。
从我可以找到的 outputStyle 需要 3 个选项:
outputStyle: 'compressed'
outputStyle: 'uncompressed'
outputStyle: 'expanded'
Run Code Online (Sandbox Code Playgroud)
这是我的魔选项,同时sass-loader
似乎拿不出的通知minimize: false
中webpack.config.js
,将听取outputStyle
选项。这将关闭所有 CSS 文件的缩小。这样就可以OptimizeCSSAssetsPlugin
发挥作用并缩小您需要的文件。
这里如果新sass-loader
代码:
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: false,
outputStyle: 'expanded'
}
}
Run Code Online (Sandbox Code Playgroud)
这是完整的 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'
};
};
Run Code Online (Sandbox Code Playgroud)