css样式文件(如.css/.less/.styl/.scss)写完之后需要有ccs相关的加载插件才能编译成最终的css文件。
1、新增一个css文件
新增一个index.css
文件
body {
margin: 0;
background-color: pink;
}
在aaa.js
中引入
import './bbb.js'
console.log("aaaa js maomao")
require("./index.css")
运行:
npm run dev
此时会发现有错误信息:
ERROR in ./src/index.css 1:5
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> body {
| margin: 0;
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
@ ./src/aaa.js 4:0-22
webpack 5.21.2 compiled with 1 error in 233 ms
ℹ 「wdm」: Failed to compile.
显示需要合适loader
来加载index.css
文件。
2、添加合适的loader配置
添加webpack配置:
module.exports = {
module: {//模块
rules: [//规则,多个loader
{
test: /\.css$/,//匹配到css结尾的文件,加载css-loader,
//css-loader负责解析@import语法,将多个css文件合并成一个
//style-loader负责把css文件插入到<head>标签中
//loader的特点:功能单一
//loader的用法:
//use:"css-loader"字符串形式只能用一个loader
//use:[]数组形式可以用多个loader
//多个loader时,加载顺序是从后往前加载(从右向左执行)
use: ["style-loader", "css-loader"]
}
]
}
}
这里添加了两个loader,分别是style-loader
和css-loader
(需先安装这两个loader);
他们的加载顺序是先用css-loader
合并css文件,然后用style-loader
把css文件插入html文件里。
3、修改css代码插入的顺序
在模版文件index.html中插入一段样式,修改背景为红色:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body{
background:red
}
</style>
</head>
<body>
<!-- 模版,此处插入js脚本 -->
<div>我是毛毛</div>
</body>
</html>
然后运行,发现并未生效。
原因是编译后的文件中,把css编译结果插到了代码<style>
样式的后面。
按照css的优先级规则,下面的样式覆盖了上面的样式。
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Document</title>
<style>body{
background:red
}
</style>
<style>body {
margin: 0;
background-color: pink;
}
</style>
</head>
<body><!-- 模版,此处插入js脚本 --><div>我是毛毛</div><script src="bundle.796a847a.js?796a847a739e67336a8d"></script></body><div id="translate-button" style="background-color: white;"</div></html>
如果你需要将代码里的样式优先级提高,就需要修改webpack将style-loader
插入的css放到<head>
标签的最上面。
展开style-loader配置,可以修改css代码插入<head>
的顺序。
use: [{
loader: "style-loader",
options: {
insertAt: "top",//将当前loader添加到<head>标签内容的最上面
}
}, "css-loader"]
运行:npm run dev
发现报错了:
ERROR in ./src/index.css
Module build failed (from ./node_modules/style-loader/dist/cjs.js):
ValidationError: Invalid options object. Style Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'insertAt'. These properties are valid:
object { injectType?, attributes?, insert?, base?, esModule?, modules? }
at validate (/Users/maomao/Documents/demo/h5/mm_webpack/node_modules/style-loader/node_modules/schema-utils/dist/validate.js:98:11)
at Object.loader (/Users/maomao/Documents/demo/h5/mm_webpack/node_modules/style-loader/dist/index.js:25:28)
@ ./src/aaa.js 4:0-22
webpack 5.21.2 compiled with 1 error in 634 ms
ℹ 「wdm」: Failed to compile.
原因是:
- 在
webpack4.0
中insertAt
已经被废弃
,现在的api是insert
, 这是一个函数。
特别鸣谢:sunshine_uniq
正确的配置如下:
use: [{
loader: "style-loader",
options: {
//将当前loader添加到<head>标签内容的最上面
insert: function (element) {
var parent = document.querySelector('head');
var lastInsertedElement = window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, parent.firstChild);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling)
} else {
parent.appendChild(element)
}
}
}
}, "css-loader"]
运行发现代码中的样式已生效,查看编译后的文件:
发现css文件的样式已经被加载到了最上面。
<html lang="en"><head><style>body {
margin: 0;
background-color: pink;
}
</style>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Document</title>
<style>
body{
background:red
}
</style>
</head>
<body><!-- 模版,此处插入js脚本 --><div>我是毛毛</div><script src="bundle.01980114.js?01980114afe45003ca7e"></script></body><div id="translate-button" style="background-color: white;"></div></html>
4、加载 less、stylus、sass
less
安装:
npm install less less-loader -D
stylus
安装:
npm install stylus stylus-loader -D
sass
安装:
npm install node-sass sass-loader -D
webpack配置:在最后加入stylus-loader
use: [{
loader: "style-loader",
options: {
//将当前loader添加到<head>标签内容的最上面
insert: function (element) {
var parent = document.querySelector('head');
var lastInsertedElement = window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, parent.firstChild);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling)
} else {
parent.appendChild(element)
}
}
}
},
"css-loader",
"stylus-loader"
]
运行:npm run dev
发现报错了:
webpack 5.21.2 compiled with 1 error in 61 ms
ℹ 「wdm」: Failed to compile.
ℹ 「wdm」: Compiling...
✖ 「wdm」: assets by status 4.94 KiB [cached] 1 asset
asset index.html 356 bytes [emitted]
cached modules 101 bytes (javascript) 997 bytes (runtime) [cached] 6 modules
./src/index.styl 392 bytes [built] [1 error]
ERROR in ./src/index.styl 1:5
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> body {
| margin: 0;
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
@ ./src/aaa.js 4:0-23
webpack 5.21.2 compiled with 1 error in 47 ms
ℹ 「wdm」: Failed to compile.
原因是原来的webpack配置错误,
应该在rules下新增.styl的样式加载配置:
module.exports = {
module: {//模块
rules: [//规则,多个loader
{
test: /\.styl$/,//匹配到styl结尾的文件,加载stylus-loader,
//css-loader负责解析@import语法,将多个css文件合并成一个
//style-loader负责把css文件插入到<head>标签中
//loader的特点:功能单一
//loader的用法:
//use:"css-loader"字符串形式只能用一个loader
//use:[]数组形式可以用多个loader
//多个loader时,加载顺序是从后往前加载(从右向左执行)
use: [{
loader: "style-loader",
options: {
// insert: "top",//将当前loader添加到<head>标签内容的最上面
insert: function (element) {
var parent = document.querySelector('head');
var lastInsertedElement = window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, parent.firstChild);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling)
} else {
parent.appendChild(element)
}
}
}
},
"css-loader",
"stylus-loader"
]
},
]
}
}
运行成功。
其他的less和sass也是一样的,安装对应的加载插件之后,将test
匹配的文件后缀修改成对应的文件后缀,
然后将最后的"stylus-loader"
改为"less-loader"
或"sass-loader"
5、抽离CSS样式
安装抽离css样式的插件:mini-css-extract-plugin
npm install mini-css-extract-plugin -D
webpack中添加如下配置:
let MiniCssExtractPlugin = require("mini-css-extract-plugin")//抽离css 插件
module.exports = {
plugins: [//存放所有插件
new MiniCssExtractPlugin({
filename: "main.css"//抽离css之后输出的文件名
})
],
module: {//模块
rules: [//规则,多个loader
{
test: /\.styl$/,//匹配到styl结尾的文件,加载stylus-loader,
use: [
MiniCssExtractPlugin.loader,//抽离成css文件,用link形式链接
"css-loader",
"stylus-loader"
]
},
]
}
}
- 引入
mini-css-extract-plugin
插件 - 将插件添加到
plugins
中,设置输出文件名 - 设置
loader
,替换掉原来的style-loader
因为<link>
与<style>
引入css的形式只需要一个就可以了。
运行:
npm run dev
查看执行结果,可以看到编译后展示的html里面,是以<link>
引入的css文件,
生成了一个名叫main.css
的文件,此文件名是webpack配置中指定的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="main.css?aab0709b375bbd6d408b" rel="stylesheet"></head>
<body>
<!-- 模版,此处插入js脚本 -->
<div>我是毛毛</div>
<script src="bundle.aab0709b.js?aab0709b375bbd6d408b"></script></body>
</html>
6、css自动生成 浏览器前缀
类似于:
这样的浏览器平台特有属性,是不是不想在写css样式的时候操心?
要是插件可以自动生成对应平台的支持属性,是不是很nice?
这里要用到:autoprefixer
插件。
autoprefixer
需要postcss-loader
的支持
安装:
npm install postcss-loader autoprefixer -D
webpack文件添加配置:
module: {//模块
rules: [//规则,多个loader
{
test: /\.styl$/,//匹配到styl结尾的文件,加载stylus-loader,
use: [
MiniCssExtractPlugin.loader,//抽离成css文件,用link形式链接
"css-loader",
"postcss-loader",
"stylus-loader"
]
},
]
}
运行npm run dev
发现有报错:
ERROR in ./src/index.styl
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/postcss-loader/src/index.js):
Error: No PostCSS Config found in: /Users/maomao/Documents/demo/h5/mm_webpack/src
at /Users/maomao/Documents/demo/h5/mm_webpack/node_modules/postcss-load-config/src/index.js:91:15
at processResult (/Users/maomao/Documents/demo/h5/mm_webpack/node_modules/webpack/lib/NormalModule.js:598:19)
at /Users/maomao/Documents/demo/h5/mm_webpack/node_modules/webpack/lib/NormalModule.js:692:5
at /Users/maomao/Documents/demo/h5/mm_webpack/node_modules/loader-runner/lib/LoaderRunner.js:399:11
at /Users/maomao/Documents/demo/h5/mm_webpack/node_modules/loader-runner/lib/LoaderRunner.js:251:18
at context.callback (/Users/maomao/Documents/demo/h5/mm_webpack/node_modules/loader-runner/lib/LoaderRunner.js:124:13)
at /Users/maomao/Documents/demo/h5/mm_webpack/node_modules/postcss-loader/src/index.js:208:9
@ ./src/aaa.js 4:0-23
1 ERROR in child compilations
webpack 5.21.2 compiled with 2 errors in 732 ms
ℹ 「wdm」: Failed to compile.
提示没有PostCSS Config
文件。
于是,
创建postcss.config.js
文件,并编辑:
module.exports = {
plugins: [require("autoprefixer")]
}
然后继续运行:npm run dev
这次不报错了,但是我这边发现运行起来的文件并没有添加浏览器平台样式。
网上找原因,发现是需要在package.json
中配置浏览器支持。
我现有的package.json
浏览器相关配置是这样的:
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
修改为:
"browserslist": [
"defaults",
"not ie < 8",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
],
再次运行:npm run dev
发现浏览器中针对css3样式添加了平台样式支持:
如:-webkit-transform: rotate(145deg);
body {
margin: 0;
background-color: #ffc0cb;
-webkit-transform: rotate(145deg);
transform: rotate(145deg);
}
7、压缩优化CSS文件
使用插件:optimize-css-assets-webpack-plugin
安装:
npm install optimize-css-assets-webpack-plugin -D
webpack文件中添加如下配置:
let OptimizeCssPlugin = require("optimize-css-assets-webpack-plugin")//压缩css 插件
module.exports = {
plugins: [//存放所有插件
new OptimizeCssPlugin()//css优化插件
],
}
运行结果,发现css文件被优化成一行:
body{margin:0;background-color:pink;-webkit-transform:rotate(145deg);transform:rotate(145deg)}
这里有个注意点!
使用:optimize-css-assets-webpack-plugin
插件之后,js的原始压缩方案将失效。
需要添加新的js压缩插件:uglifyjs-webpack-plugin
安装:
npm install uglifyjs-webpack-plugin -D
webpack文件中添加如下配置:
let UglifyJsPlugin = require("uglifyjs-webpack-plugin")//压缩js 插件
module.exports = {
plugins: [//存放所有插件
new UglifyJsPlugin(),//js优化插件
],
}
运行:npm run build
发现js文件也被优化成一行。
本节完。
完整webpack文件配置:
//webpack 是用nodejs写的,是node语法
let path = require('path')//node提供的 相对路径 转 绝对路径 的插件
let HtmlWebpackPlugin = require("html-webpack-plugin")//html webpack 插件
let MiniCssExtractPlugin = require("mini-css-extract-plugin")//抽离css 插件
let OptimizeCssPlugin = require("optimize-css-assets-webpack-plugin")//压缩css 插件
let UglifyJsPlugin = require("uglifyjs-webpack-plugin")//压缩js 插件
module.exports = {
devServer: {//开发服务器配置
port: 3000,//端口号
progress: true,//进度条
contentBase: "./dist",//返回的资源目录
compress: true//是否压缩
},
mode: "development",//模式,两种模式,产线模式"production"、开发模式"development"。产线模式会把编译文件进行压缩优化,代码变成一行。
entry: "./src/aaa.js",//入口,相对路径
output: {
filename: "bundle.[hash:8].js",//打包后的文件名
path: path.resolve(__dirname, "dist"),//打包后的路径(文件夹路径),必须是绝对路径,"__dirname"指当前路径
},
plugins: [//存放所有插件
new HtmlWebpackPlugin({
template: "./src/index.html",//模版文件(源文件)地址
filename: "index.html",//打包后文件名
minify: {
removeAttributeQuotes: true,//删除双引号
collapseWhitespace: true,//折叠空行(变成一行)
},
hash: true,//引用时文件名加上hash戳
}),
new MiniCssExtractPlugin({
filename: "main.css"//抽离css之后输出的文件名
}),
new OptimizeCssPlugin(),//css优化插件
new UglifyJsPlugin(),//js优化插件
],
module: {//模块
rules: [//规则,多个loader
{
test: /\.css$/,//匹配到css结尾的文件,加载css-loader,
//css-loader负责解析@import语法,将多个css文件合并成一个
//style-loader负责把css文件插入到<head>标签中
//loader的特点:功能单一
//loader的用法:
//use:"css-loader"字符串形式只能用一个loader
//use:[]数组形式可以用多个loader
//多个loader时,加载顺序是从后往前加载(从右向左执行)
use: [{
loader: "style-loader",
options: {
// insert: "top",//将当前loader添加到<head>标签内容的最上面
insert: function (element) {
var parent = document.querySelector('head');
var lastInsertedElement = window._lastElementInsertedByStyleLoader;
if (!lastInsertedElement) {
parent.insertBefore(element, parent.firstChild);
} else if (lastInsertedElement.nextSibling) {
parent.insertBefore(element, lastInsertedElement.nextSibling)
} else {
parent.appendChild(element)
}
}
}
},
"css-loader",
"postcss-loader"]
},
{
test: /\.styl$/,//匹配到styl结尾的文件,加载stylus-loader,
use: [
MiniCssExtractPlugin.loader,//抽离成css文件,用link形式链接
"css-loader",
"postcss-loader",
"stylus-loader"
]
},
]
}
}
暂无评论