React服务端渲染less文件引用问题

前言

  今天在对react做服务端渲染的时候,因为在使用antd组件的同时,也引用了对应的css文件,导致报错。错误信息:

1
2
/Users/xxx/xxx/node_modules/antd/lib/style/index.css:6
@font-face {

报错原因和解决方案设想

  • 报错原因
    因为服务端nodejs无法解析css,less等文件,导致报错。

  • 解决方案设想

  1. 将组件中的css,less文件的引用分离出来,不再引用less。
  2. 服务端对less文件的引用做处理。

方案实现

  • 第一种方案实现
      因为我这里使用的是antd,对组件样式的引用使用的是在.babelrc文件中设置[ "import", {"libraryName":"antd","style": "css"}],这里只需要删除掉"style": "css"这个配置即可,然后手动的将样式添加到HTML中的link标签中。
    但是这个方法是有很大缺陷,在实际开发中,我们不可能对所有的样式都才用link标签的方式引入。
  • 第二种方案实现
    (一) 通过文件类型,设置require.extensions,使得对应的文件类型采用自定义的方式引入。上代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var extensions = ['.css', '.less'];
    for (let i = 0, len = extensions.length; i < len; i++) {
    //设置不同类型的文件加载方式
    require.extensions[extensions[i]] = function (module,filename) {
    //对一些处理,比如:处理引用的文件内容,任何赋值给module.exports
    module.exports = 1;
    };
    }
    //例如:
    let a =require('./a.less');
    console.log(a); // 输出 1

  这样可以对不同类型的文件进行处理后,返回自己想得到的内容。
(二) 使用require-hacker模块,实现不同类型的文件的引用处理。上代码:

1
2
3
4
5
import require_hacker from 'require-hacker';
require_hacker.hook("less", path=> {
//对文件处理,然后返回结果
return xxx;
});

其他更好的方案

在GitHub上找到了个更好的方案。

  1. 客户端跟服务端用同一套 webpack 打包后的资源。webpack-isomorphic-tools 可以很好的解决这个问题,或者最新的 webpack 版本 target: node 也能实现。
  2. png/jpg/font 等文件直接忽略(在 babel-register 里可以设置),scss/css的话,用 css in js 的方式写。
    (网站链接)

参考:
require_hacker
nodejs模块引入机制exports&module源码