自己写 Demo 的时候用到的一个 trick, 觉得挺有意思的
我的页面是用 JavaScript 搭配 React 生成的, 前面文章提过了
那么就有两部分的 HTML, 一部分比如 <head>
, 是 gulp 生成
另一部分是 React 在浏览器当中生成的, 对应 <body>
的内容
但是, 因为 React 在 gulp 里也能跑, 其实我直接插入就好了
比如说有个 Component 叫 Page, 包含整个页面的结构
首先在浏览器当中渲染用的代码是这样:
React.render(<Page>, document.body);
而在 gulp 里调用是渲染字符串:
React.renderToString(<Page>);
那么生成的页面, 第一次加载的时候就可以是初次渲染的内容了
考虑到加载时的效果, 有必要把 CSS 从模块抽离出来, 用插件
https://github.com/webpack/extract-text-webpack-plugin
Markdown 文件
接着遇到了新的情况, 我的页面用了 Markdown, 看这里
https://github.com/Cumulo/cumulo.org
为了渲染 Markdown, 我引用了一个组件, 用于编译:
https://github.com/acdlite/react-remarkable
这个组件的使用方法是把正文内容以 source
参数传入:
<Markdown source="**Markdown is awesome!**" />
也就意味着我的 doc.md
文件需要拿到字符串才行, 加个 loader:
https://github.com/webpack/raw-loader
然后, 在 CirruScript 代码里我就可以 require :./doc/md
引用了
这个首先解决了浏览器渲染环节的问题
接下来的问题是, gulp 里怎么办, Node 环境没有 loader 的用法啊
不过还好这条路并不是堵死的, 我之前见 CoffeeScript 做过
http://coffeescript.org/documentation/docs/register.html
http://stackoverflow.com/a/17294906/883571
if require.extensions
for ext in ['.coffee', '.litcoffee', '.coffee.md']
require.extensions[ext] = loadFile
loadFile = (module, filename) ->
raw = fs.readFileSync filename, 'utf8'
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
answer = compile(stripped, {filename, sourceMap: true, literate: helpers.isLiterate filename})
sourceMaps[filename] = answer.sourceMap
module._compile answer.js, filename
大致的意思就是注册一遍对应的后缀, 让 Node 能够识别
一般比较容易用到 module._compile
, 用于执行 JavaScript 代码
具体涉及 Node 模块化机制的细节, 我不深入了, 可以看相关文章:
http://fredkschott.com/post/2014/06/require-and-the-module-system/
我不清楚全部细节, 但是加载纯文本文件的实现并不难:
if (? require.extensions) $ do
= (. require.extensions :.md) $ \ (module filename)
var code $ fs.readFileSync filename :utf8
= module.exports code
return module
如果是加载 png 文件, 也就是 base64:
if require.extensions?
fs = require 'fs'
require.extensions['.png'] = (module, filename) ->
content = fs.readFileSync filename
buf = new Buffer content
module.exports = "data:image/png;base64," + buf.toString('base64')
return module
Node API 文档上说这个用法不推荐, 而且不会保证可靠, 留意下
https://nodejs.org/api/globals.html#globals_require_extensions
用了这个以后, gulp 环境也能把 doc.md
识别和加载了
最终编译过程也把 Markdown 读取为字符串, 渲染到 React 页面里