概述
项目中通常会需要统一设置样式或者根据某种情况来定 width 和 height, 如何实现在 HTML,CSS, JS 中都能访问到的所谓共享变量呢? 其实都归功于 webpack
作者在阅读了这篇文章之后发现了使用JS 操作 CSS 代价十分昂贵, 会减慢 react 应用的渲染, 主要原因是在 react app 中, react-with-styles使用 runtime 的样式化后的组件会额外生成两个 Context.Consumer以及一个 Provider, 而这些额外的组件使得 CSS 可以监听到某些 JS 事件或者获取变量去更新样式
而静态的 CSS 不会
所以在少部分使用时还好, 但是如果是大规模使用, 比如在 table 中, 就会使得两者的性能差距变大. 但是呢, 谁不想用静态呢? 那不是产品经理有需求, 要动态的去更改啊.
以下方案就是避免了一部分情况下的 JSTOCSS 但并不是所有, 比如用户点击之后对 CSS 进行修改, 这时其实也尽量少的更改 CSS , 而是给组件添加 className, 那样至少省去了 CSS 树的重新构建过程.
设置 app
老样子
yarn init -y
安装打包工具 webpackyarn add -D webpack webpack-cli
编辑 package.json 文件
{
"script": {
"build": "webpack"
}
}
复制代码创建 globals.js文件, 里面包含了我们需要跨文件类型去获取的变量
module.exports = {
myTitle: 'Hello dev.!',
myColor: '#42ff87'
}
复制代码创建 webpack.config.js打包配置文件
module.exports = {
entry: __dirname + '/app/index.js',
output: {
path: __dirname + '/dist',
filename: 'bundle.js'
}
}
复制代码创建一个 app文件夹, 包含 index.html, index.js.文件目录结构如下:
|-- node_modules/
|-- package.json
|-- webpack.config.js
|-- globals.js
|-- app/
|-- index.html
|-- index.js
复制代码
先在 index.html中写些模板代码, 添加进变量 myTitle
Webpack shared variables!复制代码
安装html-webpack-plugin,
yarn add -D html-webpack-plugin
配置 webpack
const HTMLWebpackPlugin = require('html-webpack-plugin')
const globals = require('./globals.js')
module.exports = {
// 之前配置的 entry, output 等
plugins: [
new HTMLWebpackPlugin({
template: 'app/index.html',
templateParameters: globals // 这一步就是注入的变量, 会从这里面拿
})
]
}
复制代码
执行yarn build就会发现生成的 index.html 中的 myTitle就被替换成了Hello dev.!. 其本质原理其实就是字符串模板.
在 js 中使用变量
这是最基本的了.
import globals from '../globals.js'
document.write(
`
${JSON.stringify(globals, null, 2)}
`)
/**
{
"myTitle": "Hello dev.to !",
"myColor": "#42ff87"
}
*/
复制代码
CSS 中的变量
其实在 CSS 中是无法直接使用全局变量的, 需要用到 SASS. 不过浏览器不认识 sass 这个格式, 需要使用几个 loader, 将其转换成 css.yarn add -D sass-loader css-loader style-loader
在 app/style.scss中写以下内容, 注意我们使用的是 scss 格式, 它与 sass 的唯一区别就是加不加括号
scss
h1 {
color: $myColor
}
复制代码
sass
h1
color: $myColor
复制代码
但是因为 scss 兼容所有 css3 以及本身就是 sass3 的新语法, 所以也支持 sass-loader, 所以在项目中一般都使用 scss
接下来需要将变量注入进去. sass-loader有一个prependData的属性, 不过接受的是一个字符串而不是变量的格式, 比如$myColor: red; myTitle: '...'
module.exports = {
module: {
rules: [
{
test: /\.s(ac)ss$/i,
use: [
"style-loader", // 用于从 js 的字符串创建
"css-loader", // 将 css 转为 CommonJS
{
loader: "sass-loader", // 将 Sass 转为 CSS
options: {
prependData: "$myColor: '#42ff87'"
}
}
]
}
]
}
}
复制代码
如果像把 css 单独抽出来的话可以使用 mini-css-extract-plugin, yarn add -D mini-css-extract-plugin安装之后, 将 style-loader 替换成该插件的 loader 即可
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
module: {
rules: [
{
test: /\.s(ac)ss$/i,
use: [
MiniCssExtractPlugin.loader, // 用于从 js 的字符串创建
"css-loader", // 将 css 转为 CommonJS
{
loader: "sass-loader", // 将 Sass 转为 CSS
options: {
prependData: "$myColor: '#42ff87'"
}
}
]
}
]
}
}
复制代码