# CSS
提示
本节为可选内容,如果是开发前端组件库,那你可能需要本节内容。
# 准备
对现有的代码稍作修改,以此为基础展开本节内容。创建 src/style/element.css
写些样式类,src/util.ts
使用其样式。
/* src/style/element.css */
.ui-random-text {
display: inline-block;
font-size: 16px;
font-weight: bold;
color: cornflowerblue;
writing-mode: vertical-lr;
}
.ui-backgroud-body {
border-radius: 50%;
box-shadow: grey 10px 10px 10px 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
// src/element.ts
import "./style/element.css";
import * as util from "./util";
// 使用 background 显示图片
export async function createBackgroudImg(src: string) {
const img = await util.loadImg(src);
const div = document.createElement("div");
div.style.width = `${img.width}px`;
div.style.height = `${img.height}px`;
div.style.background = `url(${src})`;
div.classList.add("ui-backgroud-body");
return div;
}
// 创建一个有随机数的节点
export function createRandomTextElement() {
const div = document.createElement("div");
div.classList.add("ui-random-text");
div.innerText = `random: ${util.getRandomInt(1000, 9999)}`;
return div;
}
// 类、await、async 的演示代码删除,有兴趣也可以自己转化
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 构建
此时重新打包是无法工作的,因为 Webpack 只能解析 .js
文件,遇到 .css
文件时将无法正常工作。所以我们需要使用 css-loader
将 .css
解析成 .js
交给 style-loader
。而 style-loader
通过 <style>
插入到 <head>
中,实现样式应用。
# 安装
npm install style-loader css-loader --save-dev
2
// build.js
var path = require("path");
var webpack = require("webpack");
webpack(
{
// 需要设置 production,自动开启代码优化功能
// 或设置以下 optimization 手动开启代码优化功能
mode: "none", // 方便查看产物的代码,可以临时设置 none
// 入口
entry: "./src/index.ts",
// 输出
output: {
filename: "library.js",
path: path.resolve(__dirname, "dist"),
library: {
name: "library",
type: "umd",
},
},
target: ["web", "es5"],
// 顺序解析后缀名
resolve: { extensions: [".ts", ".js", ".json"] },
module: {
rules: [
{
test: /\.css$/,
// 顺序不能错,loader 从右往左执行
use: ["style-loader", "css-loader"],
},
{
test: /\.(ts)|(m?js)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
// 传入配置方式 或者 创建配置文件
options: {
presets: [
["@babel/preset-env", { debug: true, targets: "ie >= 11" }],
"@babel/preset-typescript",
],
plugins: [["@babel/plugin-transform-runtime", { corejs: 3 }]],
},
},
},
],
},
// optimization: {
// usedExports: true,
// minimize: true,
// concatenateModules: true,
// },
},
(err, stats) => {
if (err || stats.hasErrors()) {
// 这里处理错误
console.log(err, stats);
}
// 处理完成
}
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
运行 node build.js
,打开 index.html
。只有 writing-mode
在 IE 显示无效,样式在 Chrome 显示正常,Postcss 小节中将会解决该问题。除此之外,还可以发现产物依旧只有一个(dist/library.js
) 。在绝大多数 UI 组件库中, css
和 js
均是分开引入的,这个问题将在 下节 解决。
# 提取
上节说到产物只有一个 dist/library.js
文件,里面包含了 css
。而我们需要单独提取出来,这样用户才能将 css
和 js
分开引入。这里就需要用到 Webpack 的 MiniCssExtractPlugin (opens new window) 插件了,它可以将 CSS 提取成单独的文件。
注意
如果用到 MiniCssExtractPlugin
就不需要使用 style-loader
,因为这两个插件的功能是互斥的。一个是将 CSS 文件提取成单独的文件然后需要手动引入,一个是自动将 CSS 挂载到 <head></head>
中。
# 安装
npm install mini-css-extract-plugin --save-dev
2
// build.js
// ...
var MiniCssExtractPlugin = require("mini-css-extract-plugin");
webpack(
{
// ...
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
// ...
],
},
plugins: [new MiniCssExtractPlugin()],
}
// ...
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
运行 node build.js
,运行成功后会多出 dist/main.css
。这时也需要对 index.html
文件改造:手动将 .css
文件引入上。
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./dist/main.css" />
</head>
<body>
<!-- <script src="./library.js"></script> -->
<script src="./dist/library.js"></script>
<script>
// 随机数文本节点
var randomText = window.library.createRandomTextElement();
document.body.appendChild(randomText);
// 显示浏览器类型
var browserText = document.createElement("div");
browserText.innerHTML = window.library.browser();
document.body.appendChild(browserText);
// 添加图片 callback -> Promise
window.library
.createBackgroudImg("https://hxin.link/images/avatar.jpg")
.then(function(el) {
document.body.appendChild(el);
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
重新打开 index.html
,就可以发现样式应用上了。
提示
如果这里运行 node compile.js
和 node example/serve.js
打开 http://localhost:3000/
。浏览器会抛出错误 Uncaught Error: Cannot find module './style/element.css'
异常。这个是因为 compile.js
没有对 .css
文件进行处理,lib
和 es
文件夹下并没有对应的 .css
文件。这个问题会在 Postcss 单独编译 小节一同解决,如果不想使用 Postcss
,可以在 compile.js
增加对 .css
逻辑的处理。例如:将 .css
文件从 src
拷贝至对应的输出文件夹。
← TypeScript Postcss →