css-loader、style-loader和isomorphic-style-loader原理

  本文讲解css-loader、style-loader和isomorphic-style-loader的实现原理,而不会讲解它们的具体用法,具体用法请参考其他文档。我是如何知道它们是这么实现的呢?我没有看它们的源代码,而是通过查看webpack打包后生成的代码。为了留下更深刻的印象,就写下了本文。

css-loader原理

  有个很奇怪的事情,在JS文件中竟然能够导入CSS文件(通过import或require)。这是怎么做到的呢?如果JS文件要想正常被执行,那JS文件中只能包括JS语法,这是毫无疑问的。所以可以推导出,CSS文件肯定被转换成JS文件了,这个就是css-loader做的事情了。
  那CSS文件被转换成什么样子了呢?总的来说,原CSS文件的内容被转换成了一个字符串。但这还不够,为撒?一个文件既然能够被导入,那自然需要导出。所以简单推导,css-loader可以将一个css文件转换成如下内容:

module.exports = "原css文件中的样式";

这样CSS文件就成了一个合理的JS文件了,而且可以被其他JS文件引用了。这是css-loader最基本的作用,其他的都是锦上添花,比如压缩、模块化等。
  关于css-loader最后就谈一下其中的模块化。模块化是什么意思呢?我们知道css中的类名、动画名等是不具有唯一性约束的,不同的css文件或库很可能造成类名等的冲突。为了不造成冲突,css-loader可以按照一定的规则将类名等转化成具有全局唯一性的名字。即使2个文件中都有叫root的类名,经css-loader转换后,它们的类名可以完全不同,这就是css的模块化。
  模块化以后,用户完全不知道被转换后的类名,这样就没法使用了。为了让用户知道类名,css-loader就需要对转换后的内容做些改变。css-loader实际转换后的内容等价于如下伪代码:

module.exports = {
	toString: () => “原css文件中的样式(类名被转换了,代码可能也被压缩过)”
	locals: {
		[原文件中写的类名等]: “被转换后的实际类名等”
	}
}

这样通过其中的locals对象,就很容易知道被转换后的类名了。举个例子,假设css原文件中有个类名为home,导入该css文件时用变量s接收,s.locals.home的值就是被转换后的类名了。

style-loader原理

  有了css-loader,style-loader的实现就很简单了。先通过css-loader把css文件转换成一个对象,假设叫content,该对象就是上面css-loader转换css文件后导出的对象。然后简单粗暴的通过DOM操作将content中的样式插入到style标签中。最后将content.locals导出,方便用户使用类名、动画名等。同时经过css-loader和style-loader转换后的内容可以用如下伪代码表示:

var content = 【css-loader转换css文件后的结果】;
addStylesToDom(content.toString());
module.exports = content.locals;

isomorphic-style-loader原理

  我们知道了style-loader的原理,它很简单,但又很粗暴。粗暴的是,直接将样式通过DOM操作进行插入。对于浏览器环境则很好,很方便,不需要用户干预。但是对于node环境,这就没法愉快的玩耍了。node环境需要的是将样式插入到动态生成的html字符串中,而不是进行DOM操作。这时就需要用到isomorphic-style-loader,而不是style-loader。
  isomorphic-style-loader没有像style-loader那样直接进行DOM操作,而是导出了一些辅助方法,让用户依据实际情况来调用不同的方法。同时经过css-loader和isomorphic-style-loader转换后的内容可以用如下伪代码表示:

var content = 【css-loader转换css文件后的结果】;
// 方便用户使用类名等
exports = module.exports = content.locals || {}; 
exports._getContent = () => content;
// 方便用户获取样式
exports._getCss = () => context.toString();	
// 方便用户将样式插入到DOM中
exports._insertCss = 【作用同上面的addStylesToDom】;

从如上伪代码可以看出,isomorphic-style-loader主要是导出了2个函数,_getCss和_insertCss。让用户根据实际环境来调用,而不是像style-loader那样。在浏览器环境中就可以调用_insertCss(_getCss())来将样式插入到DOM中;在node环境中就不能调用_insertCss,但能调用_getCss获取样式字符串,根据实际需求来使用。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值