来源:CSS Modules 用法教程

后面项目地址:https://github.com/947133297/lwj-webpack-demo

关键是打开这一行,表示开启loader的css module功能:

{ test: /\.css$/, loader: 'style-loader!css-loader?modules' },

style-loader :用于创建style标签

css-loader:使css文件用起来像组件一样,允许require css进来,还可以启用css module功能

局部作用域测试

border.css

body {
border: 10px solid darkmagenta;
}
.qwe{
border: 10px solid black;
}
#eee{
border: 10px solid green;
}
.outer .inner{
border: 10px solid red;
}

app.css

body {
background-color: blue;
}
:global(.qwe){
font-size: 40px;
}
#eee{
color: aqua;
}
.outer .inner{
font-weight:;
}

入口js文件

require('./app.css');
var other1 = require('./border.css'); // Cannot read property 'inner' of undefined
// var html1 = '<div class="'+other1.outer.inner+'">other1</div>';
var html1 = '<div class="'+other1.outer+'"><div class="'+other1.inner+'">border test1</div></div>';
var html2 = '<div class="'+other1.qwe+'">border test2</div>';
var html3 = '<div id='+other1.eee+'>border test id</div>'; document.write(html1);
document.write(html2);
document.write(html3);

打包后的文件中有两段这样的代码(导出的标识符是base64生成的,转换前的字符串与路径和文件名相关):

exports.locals = {
"eee": "_3omJ4gpO6T45EFo0ZOMzz3",
"outer": "_2R2TiJtwoE2Ka6dR0UXOk1",
"inner": "_2Zm3l9VFNoYdhD18zUhAsL"
};
//...
exports.locals = {
"qwe": "qhJc-oYXMZ34_XRr59Qtz",
"eee": "_2EWJ0p0M9i7zNLMpM4YhOW",
"outer": "_1wB3wnxbesTSl4WbD-h9aP",
"inner": "_136k_jaRt4SbXZzJIe6J6O"
};

运行效果:

<style type="text/css">
body {
background-color: blue;
}
.qwe{
font-size: 40px;
}
#_3omJ4gpO6T45EFo0ZOMzz3{
color: aqua;
}
._2R2TiJtwoE2Ka6dR0UXOk1 ._2Zm3l9VFNoYdhD18zUhAsL{
font-weight: 900;
}
</style>
<style type="text/css">
body {
border: 10px solid darkmagenta;
}
.qhJc-oYXMZ34_XRr59Qtz{
border: 10px solid black;
}
#_2EWJ0p0M9i7zNLMpM4YhOW{
border: 10px solid green;
}
._1wB3wnxbesTSl4WbD-h9aP ._136k_jaRt4SbXZzJIe6J6O{
border: 10px solid red;
}
</style>
<body>
<div class="_1wB3wnxbesTSl4WbD-h9aP">
<div class="_136k_jaRt4SbXZzJIe6J6O">border test1</div>
</div><div class="qhJc-oYXMZ34_XRr59Qtz">border test2</div>
<div id="_2EWJ0p0M9i7zNLMpM4YhOW">border test id</div>
<h1>Hello World</h1>
<span class="qwe">3333</span>
<span id="eee">4444</span>
<div class="outer">
<div class="inner">
bold
</div>
</div>
</body>

结论:

  • 只要require了一个css,这个css会被预处理成css module(前提是打开了css-loader的module参数),然后添加由style-loader把处理后的内容到html中
  • 预处理的过程会把css中所有自定义的标识符(除标签选择符、以及global修饰外),都进行编码处理成另一个一一对应的标识符(猜测编码的主体包括选择符和文件名),这样被添加进html之后,虽然都是全局作用的,但不同css module之间同名的选择符会被编码成不同的标识,也就互不影响,就达到了“作用域”的目的了
  • 在js中使用的时候,可以通过导入的模块来获取转换后的标识符,从而为dom动态使用不同css module中样式
  • 以组件的概念来理解这里的应用场景,一个组件依赖于css,对这个css进行module预处理后,然后在js中动态获取预处理后标识,应用组件中样式。这样一来,组件间的样式就不会互相影响了。可见,要达到这样的目的,必须要动态处理样式,因为html中的类、id等不会被进行预处理。

组合class

dep.css

.depclass{
color: darkmagenta;
}

combine.css

.red{
background-color: red;
}
.content{
composes: red;
composes: depclass from './dep.css';
border: 2px solid #000;
}

入口文件添加如下代码:

var c = require('./combine.css');
var html4 = '<div class="'+c.content+'">compose test</div>';
document.write(html4);

bundle.js有如下两段代码:

exports.locals = {
"depclass": "_3o2XDTxGMaBRvs2mRiV1es"
};
//...
exports.locals = {
"red": "_1KvM5G6-rmsDcUM_AatNkH",
"content": "_3oH95_iAzM0qUNDaF3GCxv _1KvM5G6-rmsDcUM_AatNkH " + __webpack_require__(2).locals["depclass"] + ""
};

运行结果

<style type="text/css">
._1KvM5G6-rmsDcUM_AatNkH{
background-color: red;
}
._3oH95_iAzM0qUNDaF3GCxv{
border: 2px solid #000;
}
</style>
<style type="text/css">
._3o2XDTxGMaBRvs2mRiV1es{
color: darkmagenta;
}
</style>
<div class="_3oH95_iAzM0qUNDaF3GCxv _1KvM5G6-rmsDcUM_AatNkH _3o2XDTxGMaBRvs2mRiV1es">compose test</div>

结论:

  • 这次测试依赖了2个css,但运行的时候,发现只请求了一个bundle.js,而没有请求这两个css,是因为这两个css中的全部内容都打包到bundle.js中了。这就是webpack一个非常大的优点,组件化,减少网络请求次数
  • 被间接依赖的css,虽然没有在入口文件中调用require,但它的内容也被处理进来了,可见被require的css,中依赖了其他的css,这一系列的css都会被处理进来
  • compose提供一种简便的多个类的书写方式,支持组合当前文件中以及外部文件中的类;不用compose的话,自己在js中引用,然后拼接类名,再写到dom上也是没问题,如果要用到外部其他文件的话,还要自己去require,麻烦了些而已
  • 被引用的不管是直接引用(require)或者间接引用(compose),都会把这个被引用的文件内容全部加载进来

scss

修改配置文件如下:

 loaders:[
{ test: /\.s?css$/, loader: 'style-loader!css-loader?modules!sass-loader' },
]

1.scss:

$primaryColor: #333;
.s1{
background: $primaryColor;
composes: s1 from './2.scss';
}

2.scss:

$borderColor: red;
.s1{
border: 1px solid $borderColor;
}

入口文件:

var s = require('./scss/1.scss');
var html5 = '<div class="'+s.s1+'">scss test</div>';
document.write(html5);

打包:

exports.locals = {
"s1": "_2KqHQfE-Ms43DCsHA7wfbk"
}; exports.locals = {
"s1": "EhwNnMc7oenHygrKydr1t " + __webpack_require__(3).locals["s1"] + ""
};

运行结果:

<style type="text/css">
$borderColor: red;
._2KqHQfE-Ms43DCsHA7wfbk{
border: 1px solid $borderColor;
}
</style>
<style type="text/css">
.EhwNnMc7oenHygrKydr1t {
background: #333;
}
</style>
<div class="EhwNnMc7oenHygrKydr1t _2KqHQfE-Ms43DCsHA7wfbk">scss test</div>

结论:

  compose进来的scss,并没有被scss-loader所处理。所以如果要实现相关的引入功能,就只能用scss中的引入语法了。compse仅仅支持css

link和import的区别:

css module的更多相关文章

  1. Vue中scoped css和css module比较

    scoped css 官方文档 scoped css可以直接在能跑起来的vue项目中使用. 使用方法: <style scoped> h1 { color: #f00; } </st ...

  2. 同时使用antd和css module

    同时编译antd和css module,需要设置两次less识别. { test: /\.less$/, exclude: path.resolve(__dirname, './node_module ...

  3. webpack项目轻松混用css module

    前言 本文讲述css-loader开启css模块功能之后,如何与引用的npm包中样式文件不产生冲突. 比如antd-mobilenpm包的引入.在不做特殊处理的前提下,样式文件将会被转译成css mo ...

  4. 如使用Typescript撸Vue(Vue2 + TS +TSX+CSS module)

    Vue对TS的支持一致不太好,连Vue作者尤大也自嘲真香压错了宝.期待Vue3.0会用TS重构且会有较大改进.不过目前有一些第三方的库可以曲线优化对TS的支持.主要就介绍下过下面两个库来写Vue. 总 ...

  5. [React] {svg, css module, sass} support in Create React App 2.0

    create-react-app version 2.0 added a lot of new features. One of the new features is added the svgr  ...

  6. vue css module

    步骤 module <style> -> <style module> class='header' -> :class='$style.header' <t ...

  7. create-react-app 构建的项目使用 css module 方式来书写 css

    先 yarn eject 释放出来配置文件具体参见我之前写过相关的文章(这里不再重复), 找到 config 文件夹下的文件如下图所示: 找到如图所示的配置: 书写 css 的文件名例如(App.mo ...

  8. CSS Module解决全局或本地使用@keyframes无效问题

    最近使用CSSModule开发react项目,遇到一个问题,使用@keyframes无效,问题如下 /** less + css module **/ :global { .effect-bottom ...

  9. React项目中 使用 CSS Module

    安装react-app-rewired 由于新的 react-app-rewired@2.x 版本的关系,还需要安装 customize-cra.但是我们这里不需要安装 react-app-rewir ...

随机推荐

  1. poj 1186 方程的解数【折半dfs+hash】

    折半搜索,map会T所以用hash表来存状态 #include<iostream> #include<cstdio> #include<map> using nam ...

  2. python高级函数

    1 函数 1.1 函数即变量 函数定义:把一个函数体作为变量赋值给一个函数名,同时函数体存放到内存中. 函数调用:根据函数名去内存中寻找对用的函数体,找到了就执行. >>> def ...

  3. 模拟+位运算 HDOJ 5491 The Next

    题目传送门 题意:意思很简单,找一个最接近D且比D大的数,满足它的二进制表示下的1的个数在[S1, S2]之间 分析:从D + 1开始,若个数小于S1,那么从低位向高位把0替换成1直到S1就是最小值, ...

  4. 145 Binary Tree Postorder Traversal 二叉树的后序遍历

    给定一棵二叉树,返回其节点值的后序遍历.例如:给定二叉树 [1,null,2,3],   1    \     2    /   3返回 [3,2,1].注意: 递归方法很简单,你可以使用迭代方法来解 ...

  5. 合理设置apache的连接数及进程工作方式

    网站在线人数增多,访问时很慢.初步认为是服务器资源不足了,但经反复测试,一旦连接上,不断点击同一个页面上不同的链接,都能迅速打开,这种现象就是说明apache最大连接数已经满了,新的访客只能排队等待有 ...

  6. 【C#】将数据库读出的数据转换为DataTable类型集合

    return View(ConverDataReaderToDataTable(reader)); // 静态方法public static DataTable ConverDataReaderToD ...

  7. AJPFX简述Context.startService()和Context.bindService

    Context.startService()和Context.bindService 服务不能自己运行,需要通过调用Context.startService()或Context.bindService ...

  8. Koa--基于Node.js平台的下一代web开发框架的安装

    koa 是由 Express 原班人马打造的,致力于成为一个更小.更富有表现力.更健壮的 Web 框架. 使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函 ...

  9. (四)docker创建私人仓库

    (一) 简介 仓库(Repository)是集中存放镜像的地方.仓库可以 被认为是一个具体的项目或目录.例如对于仓库地址 docker.sina.com.cn/centos:centos63 来说,d ...

  10. Python3基础教程(十七)—— Virtualenv

    虚拟的 Python 环境(简称 venv) 是一个能帮助你在本地目录安装不同版本的 Python 模块的 Python 环境,你可以不再需要在你系统中安装所有东西就能开发并测试你的代码. 安装Vir ...