typescript项目中我们使用typings-for-css-modules-loader来替代css-loader实现css modules。
1、typings-for-css-modules-loader加载器介绍
Webpack
加载器,用作css-loader
的替代产品,可动态生成CSS
模块的TypeScript
类型
这句话是什么意思呢?就是编译时处理css
文件,为这些css
文件生成对应的.d.ts
声明文件并且具有css-loader
功能,用import/require
处理css
引用资源(url和@import)
,使得css
模块化,配置modules
字段可以启用css modules
。
为什么需要为css
文件生成声明文件呢?因为在typescript
项目中无论是我们自己写的代码还是导入第三方库和样式,都应该符合typescript
语言规范,就比如在react+typescript
项目中,安装了react、react-dom
后还得安装@types/react、@types/react-dom
,这两个库是react、react-dom
的声明文件。
2、typings-for-css-modules-loader加载器使用
在typescript
项目webpack
配置如下:
{
test: /\.(sc|sa|c)ss$/,
include: [path.join(__dirname, '../', './src')],
use: [
// 'style-loader', // style-loader将第二步编译出来的代码转为js代码
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: (resourcePath, context) => {
// resourcePath = E:\学习项目\从零搭建typescript+react项目\ts-react\src\index.scss
// context = E:\学习项目\从零搭建typescript+react项目\ts-react
return path.relative(path.dirname(resourcePath), context) + '/';
},
}
},
// css-loader将编译出来的代码再次编译成为符合CommonJS的代码
{
loader: 'typings-for-css-modules-loader',
options: {
modules: true, // 使用css modules
namedExport: true, // 类名导出
camelCase: true, // 支持驼峰
sass: true, // 是否使用sass
localIdentName: '[name]__[local]__[hash:base64:5]' // 定义类名
}
},
{
// 给css加上前缀
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')]
}
},
'sass-loader' // sass-loader将sass代码编译为css(默认使用node-sass)
]
}
简单解释下三个 Loader
的作用:
-
sass-loader
的作用当然是把SASS
文件编译成CSS
文件; -
typings-for-css-modules-loader
是在css-loader
上包了一层,它的选项完全兼容css-loader
。除此之外,它会为每个SASS
文件生成对应的xxx.scss.d.ts
的解释文件,这样在TypeScript
中就可以正确解析,编辑器里面也能有非常友好的代码提示。 -
style-loader
就是把样式使用标签打到页面上。
整个过程就是,读到一个 SCSS
文件,丢给 sass-loader
(调用node-sass
) 处理成 css
,然后给 typings-for-css-modules-loader
生成 xxx.scss.d.ts
文件并且把 css
处理成 JavaScript
可以使用的样子(这步其实是 css-loader
在处理,为啥要把 css
文件处理成 JavaScript
可以用的样子呢,因为 webpack
只能处理 JavaScript
,所以需要做转换),最后把处理好的给 style-loader
,页面加载的时候就会打到页面上。
其实 loader
的本质就是anything to JavaScript
,因为 Webpack
只处理 JavaScript
。记住这一点,就对为什么要用这个 loader
那个 loader
有个清晰的认识了。
比如在react + typescript
项目中,配置好typings-for-css-modules-loader
后,我们定义index.scss、index.tsx
两个文件,并在index.tsx
中导入index.scss
样式。由于启用了css modules
,所有的样式类名都会以hash字符串
替换,如果我们import './index.scss'
导入样式,那么只能在元素中className="填写对应类名对应hash字符串"
,但是类名的hash字符串
是编译时生成的,而我们在写代码时并不知道我们需要的类名会编译成哪个hash字符串
,并且hash字符串
很长不方便书写和记忆。
我们改用以模块的方式导入样式文件,但这会遇到一个问题TS2307: cannot find module '.xxx'
,因为样式文件不是AMD/CMD
规范文件,不支持模块导入,typescript
语法可以使用declare module
声明模块,我们定义一个.d.ts
文件,然后写样式模块声明,项目编译过程中会自动去读取.d.ts
这种类型的文件,所以不需要我们手动地加载他们。当然.d.ts
文件也不能随便放置在项目中,这类文件和ts文件
一样需要被typescript
编译,所以一样只能放置在tsconfig.json
中include
属性所配置的文件夹下。
// typed-css.d.ts
// scss模块声明
declare module '*.scss' {
const content: {[key: string]: any}
export default content
}
// less模块声明
declare module '*.less' {
const content: { [key: string]: any }
export default content
}
这样,样式文件就可以使用模块导入的方式了。
参考:
https://blog.csdn.net/weixin_...
https://www.npmjs.com/package...