我的目标是将CSS渲染到样式标记服务器端,类似于style-loader
插件如何在客户端执行。我知道这是不可能的,因为style-loader
直接写入DOM并且DOM在Node.js中不存在。
目前我正在使用ExtractTextPlugin,但是如果我没有将所有CSS编译成一个大文件,那么当页面加载时它会遗漏一些样式,除非我是#m在服务器上运行Webpack而不是直接编译它。
我有这个代码呈现页面:
server.jsx
const renderedContent = renderToString(
<Provider store={store} history={history}>
<RoutingContext {...renderProps} />
</Provider>
)
const finalState = store.getState()
const renderedPage = renderFullPage(renderedContent, finalState)
渲染全page.jsx
module.exports = function renderFullPage(renderedContent = undefined, state = {}) {
return '<!DOCTYPE html>' + renderToStaticMarkup(
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
{typeof __production !== 'undefined' && __production === true && <link id="css" rel="stylesheet" href="/main.css" />}
</head>
<body>
<div id="root"><div dangerouslySetInnerHTML={{__html: renderedContent}}></div></div>
<script dangerouslySetInnerHTML={{__html: 'window.__INITIAL_STATE__ =' + JSON.stringify(state)}} />
<script src="/bundle.js"></script>
</body>
</html>
)
}
我在我的React模块中需要它们时全局导入样式:
import './../../assets/styl/flex-video'
我想改变我加载CSS的方式,将所有CSS放入var中,我可以循环输出<style>
标记,style-loader
就像{typeof __production !== 'undefined' && __production === true && cssFiles.map((styles) => {
<style>{styles}</style>
})}
一样这样:
isomorphic-style-loader
这可以在Webpack中使用吗?是否有{% block content %}
<body>
<div class="container center_div" align=middle>
<h2>Indie/Alternative Artist Recommendation</h2>
<p>Enter 5 artists below and we will provide similar artists you may like</p>
<br/>
<form method="Post" action="/results">
<div class="col-xs-4" align=middle>
{{ form.artist1.label(class="col-md-6 col-sm-12") }}
{{ form.artist1(class="form-control") }}
{{ form.artist2.label(class="col-lg-6 col-md-6 col-sm-12") }}
{{ form.artist2(class="form-control") }}
{{ form.artist3.label(class="col-lg-6 col-md-6 col-sm-12") }}
{{ form.artist3(class="form-control") }}
{{ form.artist4.label(class="col-lg-6 col-md-6 col-sm-12") }}
{{ form.artist4(class="form-control") }}
{{ form.artist5.label(class="col-lg-6 col-md-6 col-sm-12") }}
{{ form.artist5(class="form-control") }}
<p><input type=submit value=Go type="button" class="btn btn-default"></p>
</div>
</form>
</div>
{% block scripts %}
<script src="{{url_for('.static', filename='js/getArtists.js')}}"></script>
{{super()}}
{% endblock %}
这样的插件能够做到这一点?如果是这样,我将如何修改我的代码?
答案 0 :(得分:1)
以下是您使用isomorphic-style-loader
所需内容的示例。
首先创建一个样式助手来自动将样式推送到DOM或将它们加载到稍后将在服务器上呈现的var中。
这是我创建的样式助手的一个例子,它被修改为接受样式文件数组(CSS,Sass,LESS,Stylus):
<强>公用事业/样式helper.jsx 强>
import React, { Component } from 'react'
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment'
const css = []
const collectOrRender = function(styles) {
let renderedCollection = []
for (let i = 0, l = styles.length; i < l; i++) {
const stylesFile = styles[i]
if (canUseDOM) {
renderedCollection[stylesFile._insertCss()]
}
css.push(stylesFile._getCss())
}
return renderedCollection
}
export function styleHelper(ComposedComponent, styles) {
return class Styles extends Component {
componentWillMount() {
this.styleRemovers = collectOrRender(styles)
}
componentWillUnmount() {
setTimeout(() => {
for (let i = 0, l = this.styleRemovers.length; i < l; i++) {
let styleRemover = this.styleRemovers[i]
typeof styleRemover === 'function' && styleRemover()
}
}, 0)
}
render() {
return <ComposedComponent {...this.props} />
}
}
}
export function renderStyles() {
return css.join('')
}
然后你必须抓住你的Style Helper并让你的模块加载。
此示例显示了在connect()
使用react-redux
时如何执行此操作。
我-module.jsx 强>
// Utilities
import { styleHelper } from 'utilities/style-helper'
const styles = [
require('normalize.css'),
require('styl/global'),
require('styl/site'),
require('styl/bubble')
]
class myModule extends Component {
render() { return (
<div />
)}
}
export default connect(
state => ({ menuIsOpen: state.collapsibleMenu.menuIsOpen })
)(styleHelper(myModule, styles))
处理客户端上的加载。现在在服务器上,您将所有这些样式存储到数组中。您需要将该数组放入HTML页面并将其放在某些<style>
标记之间。
以下是我如何做到的一个例子:
<强>渲染全page.jsx 强>
import React from 'react'
import { renderToStaticMarkup } from 'react-dom/server'
// Utilities
import { renderStyles } from './style-helper'
module.exports = function renderFullPage(renderedContent = undefined, state = {}) {
return '<!DOCTYPE html>' + renderToStaticMarkup(
<html lang="en">
<head>
{/* Critical Styles */}
<style dangerouslySetInnerHTML={{__html: renderStyles()}} />
</head>
<body>
<div id="root" dangerouslySetInnerHTML={{__html: renderedContent}}></div>
<script dangerouslySetInnerHTML={{__html: 'window.__INITIAL_STATE__ =' + JSON.stringify(state)}} />
<script src="/bundle.js"></script>
</body>
</html>
)
}
注意样式标记如何从Style Helper获取样式并将它们放在<style>
标记内。当反应加载时,它将确定要做什么,但现在服务器将只有必要的CSS才能正确显示页面。