typescript项目中咱们使用typings-for-css-modules-loader来替代css-loader实现css modules。
Webpack
加载器,用做css-loader
的替代产品,可动态生成CSS
模块的TypeScript
类型
这句话是什么意思呢?就是编译时处理css
文件,为这些css
文件生成对应的.d.ts
声明文件而且具备css-loader
功能,用import/require
处理css
引用资源(url和@import)
,使得css
模块化,配置modules
字段能够启用css modules
。css
为何须要为css
文件生成声明文件呢?由于在typescript
项目中不管是咱们本身写的代码仍是导入第三方库和样式,都应该符合typescript
语言规范,就好比在react+typescript
项目中,安装了react、react-dom
后还得安装@types/react、@types/react-dom
,这两个库是react、react-dom
的声明文件。node
在typescript
项目webpack
配置以下:react
{ 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
的做用:webpack
sass-loader
的做用固然是把 SASS
文件编译成 CSS
文件;typings-for-css-modules-loader
是在 css-loader
上包了一层,它的选项彻底兼容 css-loader
。除此以外,它会为每一个 SASS
文件生成对应的 xxx.scss.d.ts
的解释文件,这样在 TypeScript
中就能够正确解析,编辑器里面也能有很是友好的代码提示。style-loader
就是把样式使用<style>
标签打到页面上。整个过程就是,读到一个 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
,页面加载的时候就会打到页面上。web
其实 loader
的本质就是anything to JavaScript
,由于 Webpack
只处理 JavaScript
。记住这一点,就对为何要用这个 loader
那个 loader
有个清晰的认识了。typescript
好比在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字符串
很长不方便书写和记忆。npm
咱们改用以模块的方式导入样式文件,但这会遇到一个问题TS2307: cannot find module '.xxx'
,由于样式文件不是AMD/CMD
规范文件,不支持模块导入,typescript
语法可使用declare module
声明模块,咱们定义一个.d.ts
文件,而后写样式模块声明,项目编译过程当中会自动去读取.d.ts
这种类型的文件,因此不须要咱们手动地加载他们。固然.d.ts
文件也不能随便放置在项目中,这类文件和ts文件
同样须要被typescript
编译,因此同样只能放置在tsconfig.json
中include
属性所配置的文件夹下。json
// typed-css.d.ts // scss模块声明 declare module '*.scss' { const content: {[key: string]: any} export = content } // less模块声明 declare module '*.less' { const content: { [key: string]: any } export default content }
这样,样式文件就可使用模块导入的方式了。sass
参考:
https://blog.csdn.net/weixin_...
https://www.npmjs.com/package...less