开始CSS模块 | CSS-Tricks

2018-06-14 admin

这里不止一种方法来让CSS模块与JavaScript模板、CSS文件或者构建步骤运行起来。这篇文章作为CSS模块系列文章的一部分,我们学习一种方法。本文的目的就是开始一个CSS模块项目并且运行起来。

系列文章

Part 1: 什么是CSS模块以及你为什么需要它?

Part 2: 如何开始CSS模块 (你在这里!)_

Part 3: React + CSS Modules = ?

在这个项目中,要求CSS决不能依赖客户端JavaScript运行,所以构建步骤需要在部署之前将所有东西处理成可运行的HTML和CSS。我们将使用Webpack,一款构建系统和模块打包工具。在下一篇文章中我们将集中使代码处于一个渲染静态HTML的浏览器的真实的项目中。

开始吧!

安装Webpack

安装NPM和node 以后,我们需要在某处创建一个文件夹并且运行以下代码:

npm init --y

这将创建一个充满一系列默认值的package.json文件。这是我们的依赖清单——当别人npm install这个项目时需要下载和安装的依赖的指示。

Webpack 将处理我们的构建过程。它将在我们写代码的过程中监测我们的CSS,JavaScript,HTML以及执行。但是什么是Webpack? Maxime Fabre认为Webpack是一款构建系统和模块打包工具:

嗯,这两者都和我的意思,这不是我的意思,我的意思是,它结合了这两种。Webpack并没有建立自己的资源,然后分别打包你的模块,它认为你的资源是模块本身…它们能够被引入、修改、操作并且最终能够打包到你的最终文件。

如果这听起来很奇怪,不要担心。记得曾经Sass、Gulp、npm曾经都那么陌生和可怕吗?我们稍后将解决它。

让我们确信Webpack通过一个JavaScript文件定义代码的依赖关系,因此我们能够引入代码块来实现正确的“打包”。首先我们需要在全局安装Webpack,这让我们能够在我们的终端运行webpack命令:

npm install webpack -g

一旦这个完成,我们需要在我们项目的本地安装Webpack,像这样:

npm i -D webpack

现在我们需要在/src文件夹下新建一个index.js文件。通常我喜欢创建一个文件夹来存放静态资源(比如图片、字体、CSS文件和标记)。我写的代码一般都在/src文件夹下,同时那些在过程中通过机器或者编译的代码存放在/build文件夹下。我认为删除/build文件夹是完全没有问题也不会遭受任何痛苦的,因为我们完全可以运行命令行代码,它将处理/src文件夹内的东西并且再一次将它完全的重建为/build文件夹。在这种情况下,我们希望Webpack查看/src下的所有东西,执行某一过程,随后将结果的代码放入/build

/src文件夹内我们新建一个空的alert.js文件(我们随后将回看它。)我们将需要在项目的根目录,/src文件夹外创建一个webpack.config.js文件,因此我们的项目结构是这样的:

    package.json 
    webpack.config.js 
    /node_modules 
    /src
        index.js 
        alert.js

webpack.config.js文件(webpack配置文件)内,我们需要加入以下代码:

module.exports =  { 
    entry:  './src', 
    output:  { 
        path:  'build', 
        filename:  'bundle.js',  
    },  
};

每当我们运行webpack命令时,Webpack将查看/src中的所有资源建立一个依赖关系树。

返回我们的src/index.js文件中添加以下代码:

require("./alert.js");

并且在alert.js文件中写入:

alert("LOUD NOISES");

现在在我们的根目录再创建一个index.html文件,并且在<body>关闭标签前加入script标签引入我们打包的文件:

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8"> 
    <title>Document name</title> 
</head>  
<body>  
    <h1>CSS Modules demo</h1>  
    <script src="build/bundle.js"></script>  
</body>  
</html>

bundle.js就是Webpack将要生成的文件。要生成它我们需要运行webpack命令。为了让我们更方便的使用它,我们需要在package.json文件中更新scripts。我们需要在package.json文件中找到它:

"scripts":  { 
    "test":  "echo 'Error: no test specified' && exit 1"  
},

这是npm默认给我们的,但是我们可以使用以下的代码替换它,并且让我们的命令行脚本为我们运行Webpack以及打开一个浏览器窗口:

"scripts":  {  
    "start":  "webpack && open index.html"  
},

所以无论何时当我们运行npm start时我们将自动运行webpack命令以及在浏览器打开我们的index文件。让我们现在来运行一下,看看发生了什么。

✌️,运行成功了!这证明了我们的index.js文件从alert.js文件中引入了它,并且Webpack正确的打包了一切。如果我们现在删除alert.js文件,我们将在再一次运行npm start时发现一个错误:

这个错误将在Webpack未能找到引入的模块时出现。但现在,我们已经证实,我们运行的都可以完成。现在我们可以在我们的index.js中取消require,开始学习Webpack的下一步。

添加我们的第一个加载器(Loader)

Webpack中的加载器非常重要。MaxIME Fabre在这方面有他的看法:

加载器基本上是一种“当你遇到这种类型的文件时,使用这个loader加载它”的一种小型插件。

在Maxime的教程中他添加了Babel Loader,这真是一个很好的开始,因为Babel允许我们使用ES2015以及JavaScript语言的最新改进。所以,代替我们之前使用的Common.js的require函数,我们现在可以使用import。通过Babel,我们也可以使用classes(类),arrow functions(箭头函数)以及一系列其他很酷的特性:

Babel这类工具允许我们在现在就书写新的ES2015代码,并且执行一个称为转译(和预处理比较像)的任务来将代码转换为能得到浏览器很好的支持的早一些的JavaScript版本。这与Sass很像;最初使用Sass语法写代码,随后使用预处理器编译为标准的CSS。

下面的代码将安装Webpack babel loader 以及我们运行Babel需要的依赖:

npm i -D babel-loader babel-core babel-preset-es2015

在根目录下的.babelrc文件中我们可以配置预设值让其他人知道我们将使用哪种JavaScript语法:

{  
    "presets":  ["es2015"] 
}

现在我们想要Babel运行在那些我们写的.js文件上,那些我们随后安装的依赖有他们自己的语法,我们并不想弄乱它们。这时我们就需要Webpack。我们可以打开webpack.config.js文件并且用以下代码替换它:

module.exports =  { 
    entry:  './src',
    output:  { 
        path:  'build', 
        filename:  'bundle.js',  
    }, 
    module:  { 
        loaders:  [  
            { test:  /\.js/, loader:  'babel', include: __dirname +  '/src',  }  
        ], 
    } 
};

loaders数组中的test键值对告诉Webpack在什么类型的文件上操作。同时include明确告诉webpack我们想要在项目的什么地方进行操作。

让我们测试一下Babel和Webpack一起工作。在一个新的文件(src/robot.js)中,我们写入以下代码:

const greetings =  (text, person)  =>  {  
    return  `${text}, ${person}. I read you but I’m sorry, I’m afraid I can’t do that.`; 
}  
export  default greetings;

这个JavaScript文件用了一系列ES2015的新特性,比如export,constlet,箭头函数,模板字符串。

现在我们可以import那个模块到我们的src/index.js文件,像这样:

import greetings from  './robot.js'
document.write(greetings("Affirmative",  "Dave"));

最后,我们所需要做的就是再次运行npm start,我们的浏览器应该弹出一段文字:“Affirmative, Dave. I read you but I’m sorry, I’m afraid I can’t do that.”。这就证实了Babel正如它应该的工作了。

加油!尽管我们只差一步了,但目前它还不是一个CSS模块。但是在我们继续之前,让我们删除src/robot.js以及src/index.js中的代码。

加载样式

现在我们几乎让我们的模板工作了,我们将需要再添加两个loaders, css-loaderstyle-loader,我们将安装:

npm i -D css-loader style-loader

css-loader查看CSS文件的所有依赖,style-loader将这些样式直接嵌入到标记中。让我们在src/app.css中写些代码来测试:

.element { 
    background-color: blue;  
    color: white;  font-size:  20px;  
    padding:  20px; 
}

随后我们在src/index.jsimport这个样式表。

import styles from  './app.css'  
let element =  ` 
    <div class="element"> 
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur laudantium recusandae itaque libero velit minus ex reiciendis veniam. Eligendi modi sint delectus beatae nemo provident ratione maiores, voluptatibus a tempore!</p> </div> `
document.write(element);

坚持住!我们刚才将一个样式表作为JavaScript文件的依赖了吗?当然咯!但是在它正确运行以及我们知道它为什么有用之前,我们首先需要再次配置webpack.config.js

module.exports =  { 
    entry:  './src', 
    output:  { 
        path:  'build', 
        filename:  'bundle.js',  
    }, 
    module:  { 
        loaders:  [  
            { test:  /\.js/, loader:  'babel', include: __dirname +  '/src',  },  
            { test:  /\.css/, loaders:  ['style',  'css'], include: __dirname +  '/src'  }  
        ],  
    } 
};

运行npm start将看到:

这样,如果我们"Inspect Element"我们的文档,我们将发现style-loader将那个文件放入<style>标签中嵌入到了文档的<head>标签中:

让我们来盘点刚才发生的事情。我们在JavaScript文件中引入了另一个CSS文件,并且那些代码被嵌入到了网页中。所以在一个更现实的例子中,我们新建一个buttons.js文件并且依赖于buttons.css,随后将该JavaScript文件引入另一个组织我们模板和一些HTML的文件中。这会使我们的代码模块化和易于阅读!

个人来说,为了保持整洁,我倾向于有一个单独的CSS文件而不是把代码都写在一行。为了实现它,我们需要用一个名为extract textWebpack插件

将每一个入口引入(‘style.css’)的文件移动到一个单独产出的css文件。所以你的样式不再嵌入在JavaScript中,而是在一个单独的css块文件中(styles.css)。如果你的所有样式表体积很大,这将非常快,因为加载打包的样式表与JavaScript打包文件平行。

我们需要用npm安装它:

npm i -D extract-text-webpack-plugin

现在我们再一次更新webpack.config.js来引入它和我们的css loader:

var ExtractTextPlugin =  require('extract-text-webpack-plugin'); 
module.exports =  { 
    entry:  './src',
    output:  { 
        path:  'build',
        filename:  'bundle.js',  
    }, 
    module:  { 
        loaders:  [  
            { test:  /\.js/, loader:  'babel', include: __dirname +  '/src',  },
            { test:  /\.css/, loader: ExtractTextPlugin.extract("css")  }  
        ],  
    }, 
    plugins:  [  
        new  ExtractTextPlugin("styles.css")  
    ] 
};

ExtractTextPlugin现在将为我们新建一个styles.css文件!

你可能已经注意到我们已经完全移除了style-loader,因为我们不想这些样式再被注入到我们的标记中。所以,如果我们现在打开/build文件夹,我们可以看到styles.css被创建,并且我们所有的代码都在里面。现在我们可以在index.html<head>部分引入我们样式表:

<link rel="stylesheet" href="build/styles.css">

再次运行npm start —— 我们的样式已经神奇的展现在它所属于的页面了。

现在我们的CSS和HTML已经在页面起作用了,我们要怎么操作类名才能获得当前作用域的好处?我们需要像下面这样更新webpack.config.js

{ 
    test:  /\.css/, 
    loader: ExtractTextPlugin.extract('css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'),  
}

这将在类名的最后生成字符。这就是CSS模块的真正所在,通过webpack的CSSloader,hash值改变了类名。

接下来,我们用styles.element类更新index.js:

import styles from  './app.css'  
let element =  ` 
    <div class="${styles.element}"> 
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur laudantium recusandae itaque libero velit minus ex reiciendis veniam. Eligendi modi sint delectus beatae nemo provident ratione maiores, voluptatibus a tempore!</p>             </div> ` 
document.write(element);

看一下发生了什么!再次运行npm start,我们的代码已经被Webpack处理,当前作用域已经不再是问题了,因为我们的类像下面这样注入到了网页中:

<div class="app__element___1MmQg"> ... </div>

我们并没有结束,因为还有很多问题没有得到解答。我们怎样在开发环境中像这样写代码?我们怎样绕过使用document.write将标记注入到页面中?我们怎样构建我们的模块和文件?开始CSS模块并让它运行起来只完成了一半,下一步,我们必须考虑如何从另一个系统中将代码转换成这样。

在下一篇教程中,我们将学习React怎样帮助我们生成干净简练的模块,同时我们也会学习如何将很多的模板生成静态标记以及如何添加入Sass和PostCSS这样的新特性到我们的项目中。

原文链接:https://www.zcfy.cc/article/getting-started-with-css-modules-css-tricks

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-34002.html

文章标题:开始CSS模块 | CSS-Tricks

相关文章
7个你可能不认识的CSS单位
浼楁墍鍛ㄧ煡CSS鎶€鏈�鎴戜滑铏界劧寰堢啛鎮夛紝鍦ㄤ娇鐢ㄧ殑杩囩▼鍗村緢瀹规槗琚�鍥颁綇锛岃繖璁╂垜浠�鍦ㄦ柊闂�棰樺嚭鐜扮殑鏃跺€欏彉寰楀緢涓嶅埄銆� 闅忕潃web缁х画涓嶆柇鍦板彂灞曪紝瀵逛簬鏂版妧鏈�鏂拌В鍐虫柟妗堢殑瑕佹眰涔熶細涓...
2015-11-11
Vue.js原理分析之observer模块详解
介绍 observer是Vue核心中最重要的一个模块(个人认为),能够实现视图与数据的响应式更新,底层全凭observer的支持。 **注意:**本文是针对Vue@2.1.8进行分析 observer模块在Vue项目中的代码位置是src/c...
2017-03-16
css3.0参考手册
下载地址:css3.0参考手册 友情提示:如果打开空白,在手册上右键属性解除锁定即可。 ...
2015-11-12
浅析Node.js的Stream模块中的Readable对象
我一直都很不愿意扯 nodejs 的流,因为从第一次看到它我就觉得它的设计实在是太恶心了。但是没办法,Stream 规范尚未普及,而且确实有很多东西都依赖了 nodejs 的流来实现的,所以我也只能捏着鼻子硬着头皮来扯一扯这又臭又硬的 no...
2017-03-27
使用HTML+CSS+JS制作简单的网页菜单界面
写ABROAD项目用到了标签这个东东,其实标签在WEB上到处可见,图中就依次显示了DCC文章发布器、ABROAD后台添加数据、百度图片搜索、sf发布博客文章时贴标签的样式——标签就像浏览器里原生的checkbox一样,不过checkbox实...
2017-03-27
深入探寻seajs的模块化与加载方式
由于一直在使用,所以了解了下seajs的源代码。这里是我对下面几个问题的理解: 1、seajs的require(XXX)的方法是怎样实现模块加载的? 2、为什么需要预加载? 3、为什么需要构建工具? 4、构建前后的代码究竟有些什么区别,为什...
2017-03-22
Node.js之网络通讯模块实现浅析
前言 想必我们在用Node.js用的最多的应该是创建http服务,所以对于每个Web开发工程师而言,Node.js的网络相关模块学习是必不可少。 Node.js的网络模块架构 在Node.js的模块里面,与网络相关的模块有Net、DNS、H...
2017-04-05
javascript制作的简单注册模块表单验证
一个注册框  进行表单验证处理 如图 有简单的验证提示功能 代码思路也比较简单 输入框失去焦点时便检测,并进行处理 表单具有 onsubmit = &quot;return check()&quot;行为,处理验证情况 点击提交表单按钮时...
2017-03-22
nodejs的压缩文件模块archiver用法示例
本文实例讲述了nodejs的压缩文件模块archiver用法。分享给大家供大家参考,具体如下: 发现了个更好用的 zip-local https://www.npmjs.com/package/zip-local var zipper = ...
2017-03-06
javascript实现动态导入js与css等静态资源文件的方法
本文实例讲述了javascript实现动态导入js与css等静态资源文件的方法。分享给大家供大家参考。具体实现方法如下: &#x2F;** * 动态导入静态资源文件js&#x2F;css *&#x2F; var $import = fu...
2017-03-27
回到顶部