加载css
插件
- css-loader
css-loader 会对 @import 和 url() 进行处理,就像 js 解析 import/require() 一样
- style-loader
采用标签把 CSS 插入到 DOM 中
安装插件
yarn add style-loader css-loader -D
yarn add v1.22.4
info No lockfile found.
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > style-loader@2.0.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning " > css-loader@5.1.2" has unmet peer dependency "webpack@^4.27.0 || ^5.0.0".
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 30 new dependencies.
info Direct dependencies
├─ css-loader@5.1.2
└─ style-loader@2.0.0
info All dependencies
├─ @types/json-schema@7.0.7
├─ ajv-keywords@3.5.2
├─ ajv@6.12.6
├─ big.js@5.2.2
├─ camelcase@6.2.0
├─ colorette@1.2.2
├─ css-loader@5.1.2
├─ emojis-list@3.0.0
├─ fast-deep-equal@3.1.3
├─ fast-json-stable-stringify@2.1.0
├─ indexes-of@1.0.1
├─ json-schema-traverse@0.4.1
├─ json5@2.2.0
├─ lru-cache@6.0.0
├─ minimist@1.2.5
├─ nanoid@3.1.21
├─ postcss-modules-extract-imports@3.0.0
├─ postcss-modules-local-by-default@4.0.0
├─ postcss-modules-scope@3.0.0
├─ postcss-modules-values@4.0.0
├─ postcss-selector-parser@6.0.4
├─ postcss@8.2.8
├─ punycode@2.1.1
├─ semver@7.3.4
├─ source-map@0.6.1
├─ style-loader@2.0.0
├─ uniq@1.0.1
├─ uri-js@4.4.1
├─ util-deprecate@1.0.2
└─ yallist@4.0.0
✨ Done in 10.36s.
webpack配置
项目更目录下新建webpack.config.js或者webpackfile.js。配置如下:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.[hash:8].js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: 'style-loader',
options: {
insert: 'head',
},
},
'css-loader',
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
hash: true,
}),
]
}
⚠️注意:插件执行顺序是自右到左执行
然后控制台执行
$ webpack
打包后的dist/index.html中插入了css样式
加载less
插件
- less-loader
webpack 将 Less 编译为 CSS 的 loader
安装插件
yarn add less less-loader -D
yarn add v1.22.4
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > css-loader@5.1.2" has unmet peer dependency "webpack@^4.27.0 || ^5.0.0".
warning " > style-loader@2.0.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning " > less-loader@8.0.0" has unmet peer dependency "webpack@^5.0.0".
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 20 new dependencies.
info Direct dependencies
├─ less-loader@8.0.0
└─ less@4.1.1
info All dependencies
├─ copy-anything@2.0.3
├─ debug@3.2.7
├─ errno@0.1.8
├─ graceful-fs@4.2.6
├─ iconv-lite@0.4.24
├─ image-size@0.5.5
├─ is-what@3.14.1
├─ klona@2.0.4
├─ less-loader@8.0.0
├─ less@4.1.1
├─ make-dir@2.1.0
├─ mime@1.6.0
├─ ms@2.1.3
├─ needle@2.6.0
├─ parse-node-version@1.0.1
├─ pify@4.0.1
├─ prr@1.0.1
├─ safer-buffer@2.1.2
├─ sax@1.2.4
└─ tslib@1.14.1
✨ Done in 1.05s.
⚠️注意:less-loader依赖less,所以需要同步安装less
webpack配置
在css-loader插件执行之前采用less-loader编译less成css。配置webpack解析项目中.less文件如下:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.[hash:8].js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: 'style-loader',
options: {
insert: 'head',
},
},
'css-loader',
],
},
{
test: /\.less$/i,
use: [
{
loader: 'style-loader',
options: {
insert: 'head',
},
},
'css-loader',
'less-loader'
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
hash: true,
}),
]
}
加载scss
插件
- sass-loader
加载 Sass/SCSS 文件并将他们编译为 CSS
安装插件
yarn add sass sass-loader -D
yarn add v1.22.4
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > css-loader@5.1.2" has unmet peer dependency "webpack@^4.27.0 || ^5.0.0".
warning " > less-loader@8.0.0" has unmet peer dependency "webpack@^5.0.0".
warning " > style-loader@2.0.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning " > sass-loader@11.0.1" has unmet peer dependency "webpack@^5.0.0".
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 18 new dependencies.
info Direct dependencies
├─ sass-loader@11.0.1
└─ sass@1.32.8
info All dependencies
├─ anymatch@3.1.1
├─ binary-extensions@2.2.0
├─ braces@3.0.2
├─ chokidar@3.5.1
├─ fill-range@7.0.1
├─ fsevents@2.3.2
├─ glob-parent@5.1.2
├─ is-binary-path@2.1.0
├─ is-extglob@2.1.1
├─ is-glob@4.0.1
├─ is-number@7.0.0
├─ neo-async@2.6.2
├─ normalize-path@3.0.0
├─ picomatch@2.2.2
├─ readdirp@3.5.0
├─ sass-loader@11.0.1
├─ sass@1.32.8
└─ to-regex-range@5.0.1
✨ Done in 2.09s.
⚠️注意:sass-loader依赖sass,所以需要同步安装sass
webpack配置
在css-loader插件执行之前采用sass-loader编译scss成css。配置webpack解析项目中.scss文件如下:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.[hash:8].js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: 'style-loader',
options: {
insert: 'head',
},
},
'css-loader',
],
},
{
test: /\.less$/i,
use: [
{
loader: 'style-loader',
options: {
insert: 'head',
},
},
'css-loader',
{
loader: 'sass-loader',
options: {
...sass-loader options配置
}
}
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
hash: true,
}),
]
}
提取style到单独样式文件
当项目中的样式文件很多时,直接插入到html文件中会影响页面加载速度。我们可以采用mini-css-extract-plugin插件把样式输出到独立的文件中
安装插件
yarn add mini-css-extract-plugin -D
yarn add v1.22.4
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > css-loader@5.1.2" has unmet peer dependency "webpack@^4.27.0 || ^5.0.0".
warning " > less-loader@8.0.0" has unmet peer dependency "webpack@^5.0.0".
warning " > sass-loader@11.0.1" has unmet peer dependency "webpack@^5.0.0".
warning " > style-loader@2.0.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning " > mini-css-extract-plugin@1.3.9" has unmet peer dependency "webpack@^4.4.0 || ^5.0.0".
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 3 new dependencies.
info Direct dependencies
└─ mini-css-extract-plugin@1.3.9
info All dependencies
├─ mini-css-extract-plugin@1.3.9
├─ source-list-map@2.0.1
└─ webpack-sources@1.4.3
✨ Done in 0.81s.
webpack配置
采用 mini-css-extract-plugin 插件把css抽离成单独的 css 文件后,就不再需要 style-loader 插件把 css 插入到 html 中了,把 style-loader 替换成 MiniCssExtractPlugin的loader。配置如下
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.[hash:8].js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
},
{
test: /\.less$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
hash: true, //引入css时带hash后缀,防止样式文件缓存
}),
new MiniCssExtractPlugin({
filename: 'main.css', //指定输出文件名
}),
]
}
添加浏览器前缀
postcss之于css相当于babel之于js。我们可以利用postcss插件给css添加浏览器前缀,自动适配不同内核的浏览器。
安装插件
yarn add postcss-loader postcss-preset-env -D
yarn add v1.22.4
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > css-loader@5.1.2" has unmet peer dependency "webpack@^4.27.0 || ^5.0.0".
warning " > less-loader@8.0.0" has unmet peer dependency "webpack@^5.0.0".
warning " > mini-css-extract-plugin@1.3.9" has unmet peer dependency "webpack@^4.4.0 || ^5.0.0".
warning " > sass-loader@11.0.1" has unmet peer dependency "webpack@^5.0.0".
warning " > style-loader@2.0.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning " > postcss-loader@5.2.0" has unmet peer dependency "webpack@^5.0.0".
warning " > postcss-loader@5.2.0" has unmet peer dependency "postcss@^7.0.0 || ^8.0.1".
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 69 new dependencies.
info Direct dependencies
├─ postcss-loader@5.2.0
└─ postcss-preset-env@6.7.0
info All dependencies
├─ @babel/code-frame@7.12.13
├─ @babel/helper-validator-identifier@7.12.11
├─ @babel/highlight@7.13.10
├─ @types/parse-json@4.0.0
├─ ansi-styles@3.2.1
├─ autoprefixer@9.8.6
├─ browserslist@4.16.3
├─ callsites@3.1.0
├─ caniuse-lite@1.0.30001199
├─ chalk@2.4.2
├─ color-convert@1.9.3
├─ color-name@1.1.3
├─ cosmiconfig@7.0.0
├─ css-blank-pseudo@0.1.4
├─ css-has-pseudo@0.10.0
├─ css-prefers-color-scheme@3.1.1
├─ cssdb@4.4.0
├─ electron-to-chromium@1.3.687
├─ error-ex@1.3.2
├─ escalade@3.1.1
├─ escape-string-regexp@1.0.5
├─ flatten@1.0.3
├─ import-fresh@3.3.0
├─ is-arrayish@0.2.1
├─ js-tokens@4.0.0
├─ json-parse-even-better-errors@2.3.1
├─ lines-and-columns@1.1.6
├─ lodash.template@4.5.0
├─ lodash.templatesettings@4.2.0
├─ node-releases@1.1.71
├─ normalize-range@0.1.2
├─ num2fraction@1.2.2
├─ parent-module@1.0.1
├─ parse-json@5.2.0
├─ path-type@4.0.0
├─ postcss-attribute-case-insensitive@4.0.2
├─ postcss-color-functional-notation@2.0.1
├─ postcss-color-gray@5.0.0
├─ postcss-color-hex-alpha@5.0.3
├─ postcss-color-mod-function@3.0.3
├─ postcss-color-rebeccapurple@4.0.1
├─ postcss-custom-media@7.0.8
├─ postcss-custom-properties@8.0.11
├─ postcss-custom-selectors@5.1.2
├─ postcss-dir-pseudo-class@5.0.0
├─ postcss-double-position-gradients@1.0.0
├─ postcss-env-function@2.0.2
├─ postcss-focus-visible@4.0.0
├─ postcss-focus-within@3.0.0
├─ postcss-font-variant@4.0.1
├─ postcss-gap-properties@2.0.0
├─ postcss-image-set-function@3.0.1
├─ postcss-initial@3.0.2
├─ postcss-lab-function@2.0.1
├─ postcss-loader@5.2.0
├─ postcss-logical@3.0.0
├─ postcss-media-minmax@4.0.0
├─ postcss-nesting@7.0.1
├─ postcss-overflow-shorthand@2.0.0
├─ postcss-page-break@2.0.0
├─ postcss-place@4.0.1
├─ postcss-preset-env@6.7.0
├─ postcss-pseudo-class-any-link@6.0.0
├─ postcss-replace-overflow-wrap@3.0.0
├─ postcss-selector-matches@4.0.0
├─ postcss-selector-not@4.0.1
├─ resolve-from@4.0.0
├─ supports-color@6.1.0
└─ yaml@1.10.0
✨ Done in 2.36s.
webpack配置
postcss-loader 和 postcss-preset-env 插件主要是处理css样式前缀,所以必须在css-loader加载css之前处理。配置如下:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.[hash:8].js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
},
{
test: /\.less$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-preset-env',
{
browsers: 'last 2 versions',
},
],
},
},
},
'less-loader'
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
hash: true, //引入css时带hash后缀,防止样式文件缓存
}),
new MiniCssExtractPlugin({
filename: 'main.css', //指定输出文件名
}),
]
}
也可以把postcss配置单独写到配置文件 ++postcss.config.js++。如:
module.exports = {
plugins: [
require('postcss-preset-env')({
browsers: 'last 2 versions',
}),
],
}
压缩style样式文件
webpack在production模式下打包默认会把js进行压缩,但是不会压缩css,需要我们借助插件去压缩css。如 optimize-css-assets-webpack-plugin、css-minimizer-webpack-plugin。这里以optimize-css-assets-webpack-plugin插件为例。
安装插件
yarn add optimize-css-assets-webpack-plugin -D
yarn add v1.22.4
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
warning " > css-loader@5.1.2" has unmet peer dependency "webpack@^4.27.0 || ^5.0.0".
warning " > less-loader@8.0.0" has unmet peer dependency "webpack@^5.0.0".
warning " > mini-css-extract-plugin@1.3.9" has unmet peer dependency "webpack@^4.4.0 || ^5.0.0".
warning " > postcss-loader@5.2.0" has unmet peer dependency "webpack@^5.0.0".
warning " > postcss-loader@5.2.0" has unmet peer dependency "postcss@^7.0.0 || ^8.0.1".
warning " > sass-loader@11.0.1" has unmet peer dependency "webpack@^5.0.0".
warning " > style-loader@2.0.0" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning " > optimize-css-assets-webpack-plugin@5.0.4" has unmet peer dependency "webpack@^4.0.0".
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
success Saved 103 new dependencies.
info Direct dependencies
└─ optimize-css-assets-webpack-plugin@5.0.4
info All dependencies
├─ @types/q@1.5.4
├─ argparse@1.0.10
├─ boolbase@1.0.0
├─ caller-callsite@2.0.0
├─ caller-path@2.0.0
├─ coa@2.0.2
├─ color-string@1.5.5
├─ color@3.1.3
├─ css-color-names@0.0.4
├─ css-declaration-sorter@4.0.1
├─ css-select-base-adapter@0.1.1
├─ css-select@2.1.0
├─ css-tree@1.0.0-alpha.37
├─ css-what@3.4.2
├─ cssnano-preset-default@4.0.7
├─ cssnano-util-raw-cache@4.0.1
├─ cssnano-util-same-parent@4.0.1
├─ cssnano@4.1.10
├─ csso@4.2.0
├─ dom-serializer@0.2.2
├─ domelementtype@1.3.1
├─ domutils@1.7.0
├─ dot-prop@5.3.0
├─ entities@2.2.0
├─ es-to-primitive@1.2.1
├─ esprima@4.0.1
├─ get-intrinsic@1.1.1
├─ has-bigints@1.0.1
├─ hex-color-regex@1.1.0
├─ hsl-regex@1.0.0
├─ hsla-regex@1.0.0
├─ html-comment-regex@1.1.2
├─ is-absolute-url@2.1.0
├─ is-bigint@1.0.1
├─ is-boolean-object@1.1.0
├─ is-callable@1.2.3
├─ is-color-stop@1.1.0
├─ is-date-object@1.0.2
├─ is-directory@0.3.1
├─ is-negative-zero@2.0.1
├─ is-number-object@1.0.4
├─ is-obj@2.0.0
├─ is-regex@1.1.2
├─ is-resolvable@1.1.0
├─ is-svg@3.0.0
├─ is-symbol@1.0.3
├─ json-parse-better-errors@1.0.2
├─ last-call-webpack-plugin@3.0.0
├─ lodash.memoize@4.1.2
├─ lodash.uniq@4.5.0
├─ lodash@4.17.21
├─ mdn-data@2.0.4
├─ mkdirp@0.5.5
├─ normalize-url@3.3.0
├─ nth-check@1.0.2
├─ object-inspect@1.9.0
├─ object.assign@4.1.2
├─ object.getownpropertydescriptors@2.1.2
├─ object.values@1.1.3
├─ optimize-css-assets-webpack-plugin@5.0.4
├─ postcss-calc@7.0.5
├─ postcss-colormin@4.0.3
├─ postcss-convert-values@4.0.1
├─ postcss-discard-comments@4.0.2
├─ postcss-discard-duplicates@4.0.2
├─ postcss-discard-empty@4.0.1
├─ postcss-discard-overridden@4.0.1
├─ postcss-merge-longhand@4.0.11
├─ postcss-merge-rules@4.0.3
├─ postcss-minify-font-values@4.0.2
├─ postcss-minify-gradients@4.0.2
├─ postcss-minify-params@4.0.2
├─ postcss-minify-selectors@4.0.2
├─ postcss-normalize-charset@4.0.1
├─ postcss-normalize-display-values@4.0.2
├─ postcss-normalize-positions@4.0.2
├─ postcss-normalize-repeat-style@4.0.2
├─ postcss-normalize-string@4.0.2
├─ postcss-normalize-timing-functions@4.0.2
├─ postcss-normalize-unicode@4.0.1
├─ postcss-normalize-url@4.0.1
├─ postcss-normalize-whitespace@4.0.2
├─ postcss-ordered-values@4.1.2
├─ postcss-reduce-initial@4.0.3
├─ postcss-reduce-transforms@4.0.2
├─ postcss-svgo@4.0.2
├─ postcss-unique-selectors@4.0.1
├─ q@1.5.1
├─ rgb-regex@1.0.1
├─ rgba-regex@1.0.0
├─ simple-swizzle@0.2.2
├─ sprintf-js@1.0.3
├─ stable@0.1.8
├─ string.prototype.trimend@1.0.4
├─ string.prototype.trimstart@1.0.4
├─ stylehacks@4.0.3
├─ svgo@1.3.2
├─ timsort@0.3.0
├─ unbox-primitive@1.0.0
├─ unquote@1.1.1
├─ util.promisify@1.0.1
├─ vendors@1.0.4
└─ which-boxed-primitive@1.0.2
✨ Done in 3.05s.
webpack配置
借助webpack(@4+)的Optimization手动配置优化项。如:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCss = require('optimize-css-assets-webpack-plugin')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.[hash:8].js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
minimizer: [
new OptimizeCss()
],
},
module: {
rules: [
{
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
},
{
test: /\.less$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-preset-env',
{
browsers: 'last 2 versions',
},
],
},
},
},
'less-loader'
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
hash: true, //引入css时带hash后缀,防止样式文件缓存
}),
new MiniCssExtractPlugin({
filename: 'main.css', //指定输出文件名
}),
]
}
然后控制台执行
$ webpack
发现css确实被压缩了,但是js未被压缩。那是因为webpack默认只压缩js,如果采用手动配置优化项,则接触默认压缩js,对js的压缩也需要用户手动配置。于是我们借助 uglifyjs-webpack-plugin 压缩js。
$ yarn add uglifyjs-webpack-plugin -D
在webpack中的optimization中也把js压缩插件配上即可。
✨ ✨ 最后附上完整的webpack配置:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCss = require('optimize-css-assets-webpack-plugin')
const UglifyjsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
devServer: {
port: 3000,
progress: true,
contentBase: './dist',
open: true,
},
optimization: {
minimizer: [
new OptimizeCss(),
new UglifyjsPlugin({
cache: true,
parallel: true,
sourceMap: true,
}),
],
},
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.[hash:8].js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'less-loader',
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
hash: true,
}),
new MiniCssExtractPlugin({
filename: 'main.css',
}),
],
}