当我们在一个文件中引入一个CSS
文件,然后去 npm run build
的时候又会报错,这是因为前面说过Webpack
默认只认识JS
文件,所以我还需要安装一些loader
去处理CSS
这样的样式文件。
.avatar {
width: 200px;
height: 200px;
}
import imgUrl from "../static/demo.jpg";
import './index.css';
function creatAvatar() {
var img = new Image();
img.src = imgUrl;
img.classList.add("avatar");
var app = document.getElementById("app");
app.append(img);
}
export default creatAvatar;
style-loader 和 css-loader
style-loader | webpack 中文文档
css-loader | webpack 中文文档
首先我们需要安装两个Loader
:
$ npm install style-loader css-loader --save-dev
进行配置:
module.exports = {
// ...
module: {
rules: [
{
test: /\.jpg$/,
use: {
loader: "url-loader",
options: {
// 如果图片小于2048(2kb)字节的话就处理成base64的字符串
limit: 2048
}
}
},
{
test: /\.css$/,
// 当使用多个loader 的时候可以用数组(从后向前执行),先执行 css-loader 再执行 style-loader
use: ["style-loader", "css-loader"]
}
]
}
}
当JS
文件看到.css
文件就会根据module
中的loader
对css
文件进行打包。
现在我们来改动一下:
.avatar {
width: 200px;
height: 200px;
}
@import './avatar.css'
import './index.css';
// ...
JS
文件不变,继续引入index.css
,然后执行 npm run build
打包依然是正常。
:::info
这是因为css-loader
会帮我们分析出几个css
文件之间依赖的关系,把多个css
文件合并为一段css
。style-loader
得到css-loader
处理后的结果把css
代码挂载到页面的head
标签中 。
:::
所以**css-loader**
和**style-loader**
必须连起来使用。
如何使用 scss/less
我们接着修改文件:
/* 重命名index.css ==> index.scss */
body {
.avatar {
width: 200px;
height: 200px;
}
}
import imgUrl from "../static/demo.jpg";
import './index.scss';
// ...
当我们运行npm run build
的时候肯定报错,这是因为Webpack
又不认识.scss
文件了。
然后我们修改配置文件webpack.config.js
:
module.exports = {
// ...
module:{
rules: [
{
test: /\.jpg$/,
use: {
loader: "url-loader",
options: {
limit: 2048
}
}
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader"]
}
]
}
}
这样虽然能编译成功,但是css
的样式却没有效果,这是因为scss
的语法并没有被编译:
所以我要安装sass-loader
:
$ npm install sass-loader node-sass --save-dev
修改配置文件:
module.exports = {
// ...
module:{
rules: [
{
test: /\.jpg$/,
use: {
loader: "url-loader",
options: {
limit: 2048
}
}
},
{
test: /\.scss$/,
// 执行的顺序 sass-loader的结果- css-loader的结果- style-loader,所以是从后往前的执行顺序
use: ["style-loader", "css-loader","sass-loader"]
}
]
}
}
这个时候再运行就可以编译了。
使用 postcss-loader
现在我们给.avatar
添加一个CSS3
的属性:
body {
.avatar {
width: 200px;
height: 200px;
transform: translate(100px);
}
}
我们编译后发现图片确实进行位移了,但是却没有浏览器兼任的前缀(部分浏览器需要兼容CSS3
的新属性)。
我们可以使用 postcss-loader
来解决这个问题。
安装:
# 安装 postcss-loader
$ npm install postcss-loader -D
# 还需要安装一个postcss 的插件
$ npm install autoprefixer -D
配置:
module.exports = {
// ...
module:{
rules: [
{
test: /\.jpg$/,
use: {
loader: "url-loader",
options: {
limit: 2048
}
}
},
{
test: /\.scss$/,
// 执行的顺序 sass-loader 的结果 css-loader 的结果 style-loader,所以是从后往前的执行顺序
use: ["style-loader", "css-loader", "sass-loader", "postcss-loader"]
}
]
}
}
另外还需要新加一个postcss
的配置文件postcss.config.js
(和webpack.config.js
一样,配置文件名不能进行更改,Loader
将会自动搜索配置文件)。
module.exports = {
// 插件 plugins 可以是对象或者数组
plugins: [
// 给css3的新属性添加浏览器兼容(比如:-webkit-)
require("autoprefixer")
]
}
如果不生效则可能是当前浏览器版本已经足够支持CSS3
的属性,所以不会新增浏览器前缀,如果确实想要进行拼接,可以在package.json
文章中新增如下配置:
{
"scripts": {
"build": "webpack"
},
// 新增 browserslist 属性告知浏览器的版本
"browserslist": [
"> 1%",
"last 2 versions"
],
"devDependencies": {
"autoprefixer": "^10.4.13",
"css-loader": "^5.2.7",
"file-loader": "^6.2.0",
"postcss-loader": "^4.2.0",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10"
}
}
配置具体的 css-loader
在 module.rules.use.loader
除了用数组字符串的形式,还可以使用数组对象的方式。
module.exports = {
// ...
module:{
rules: [
{
test: /\.jpg$/,
use: {
loader: "url-loader",
options: {
limit: 2048
}
}
},
{
test: /\.scss$/,
// 执行的顺序 sass-loader 的结果 css-loader 的结果 style-loader,所以是从后往前的执行顺序
use: [
"style-loader",
{
loader: "css-loader",
options: {
// 表示仍然要继续从 postcss-loader 开始执行
importLoaders: 2
}
}, "sass-loader", "postcss-loader"
]
}
]
}
}
@import "./test.scss";
/* Webpack 的某些版本在 index.js 文件引入 index.scss 的时候已经执行到 css-loader 了,
如果 index.scss 文件又引入了 test.scss 文件就会出现解析问题 */
body {
.avatar {
width: 200px;
height: 200px;
transform: translate(100px);
}
}
在webpack.config.js
配置文件中,如果不配置importLoaders
的话,在index.scss
文件中引入test.scss
文件就不会从postcss-loader
和 sass-loader
进行编译。
CSS 模块化
当我们在同一个JS
文件中创建两个照片,就像这样:
import creatAvatar from './creatAvatar';
import creatAvatar02 from './creatAvatar02';
import './index.scss';
creatAvatar();
creatAvatar02();
import imgUrl from "../static/demo.jpg";
function creatAvatar() {
var img = new Image();
img.src = imgUrl;
img.classList.add("avatar");
var app = document.getElementById("app");
app.append(img);
}
export default creatAvatar;
import imgUrl from "../static/demo.jpg";
function creatAvatar() {
var img = new Image();
img.src = imgUrl;
img.classList.add("avatar");
var app = document.getElementById("app");
app.append(img);
}
export default creatAvatar;
这个时候index.js
文件引入的scss
文件就成了全局的样式文件,影响着页面全部的图片。
我们可以在weboack.config.js
文件中对css-loader
进行配置实现隔离模块化:
moduele.exports = {
// ...
mode:{
rules:[{
test: /\.scss$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
importLoaders: 2,
// 实现样式模块化
modules: true
}
},
"sass-loader",
"postcss-loader"
]
}]
}
}
import header from './header'
import footer from './footer'
import creatAvatar from './creatAvatar';
import creatAvatar02 from './creatAvatar02';
creatAvatar();
creatAvatar02();
import imgUrl from "../static/demo.jpg";
import style from './index.scss';
function creatAvatar() {
var img = new Image();
img.src = imgUrl;
img.classList.add(style.avatar);
var app = document.getElementById("app");
app.append(img);
}
export default creatAvatar;
import imgUrl from "../static/demo.jpg";
function creatAvatar() {
var img = new Image();
img.src = imgUrl;
img.classList.add("avatar");
var app = document.getElementById("app");
app.append(img);
}
export default creatAvatar;
这样就保证了css
样式只有在文件引入后才会生效。