te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Webpack SCSS "Flicker" before pageload - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Webpack SCSS "Flicker" before pageload - Stack Overflow

programmeradmin2浏览0评论

I am working on an isomorphic React+Flux+express app and using webpack loaders for my sass (with sass-loader) and jsx files. I am not sure how to inject my stylesheets into a server side template. I took a look at the Extract Text Plugin for this purpose, but I really want to be able to use hot module replacement. Right now, I am loading my main.scss file in a React ponent like this:

if (typeof window !== 'undefined') {
  require("!style!css!sass!../../../styles/main.scss");
}

This works well for loading an individual stylesheet in a ponent, but there is a flicker before the React part is mounted. I understand that this is because this is injecting the stylesheet after my client-side app has loaded, so the stylesheet is not immediately available. This leads to the actual question: is there a way to inject this style-sheet into my server-side template while still using the webpack loader, or does this call for a separate gulpfile or express middleware? I was previously using a gulpfile to build my stylesheets, but I will end up having a lot of stylesheets and don't want them all jammed into one file.

I am working on an isomorphic React+Flux+express app and using webpack loaders for my sass (with sass-loader) and jsx files. I am not sure how to inject my stylesheets into a server side template. I took a look at the Extract Text Plugin for this purpose, but I really want to be able to use hot module replacement. Right now, I am loading my main.scss file in a React ponent like this:

if (typeof window !== 'undefined') {
  require("!style!css!sass!../../../styles/main.scss");
}

This works well for loading an individual stylesheet in a ponent, but there is a flicker before the React part is mounted. I understand that this is because this is injecting the stylesheet after my client-side app has loaded, so the stylesheet is not immediately available. This leads to the actual question: is there a way to inject this style-sheet into my server-side template while still using the webpack loader, or does this call for a separate gulpfile or express middleware? I was previously using a gulpfile to build my stylesheets, but I will end up having a lot of stylesheets and don't want them all jammed into one file.

Share Improve this question asked Feb 17, 2015 at 19:36 johnnyutahjohnnyutah 6851 gold badge7 silver badges23 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 13

So the idea here is to have webpack pile with two separate configurations, one targeted for web (the browser), the other targeted for node (server-side). The server-side bundle can be required in other node/express code to build the pre-rendered HTML with the css.

There's a full example here, and I'll walk you through the relevant parts of it. https://github./webpack/react-starter

The prerender.html in app is the server-side template the author is using. Notice the following two lines of code:

<link rel="stylesheet" href="STYLE_URL">
<script src="SCRIPT_URL"></script>

See the config for webpack here https://github./webpack/react-starter/blob/master/make-webpack-config.js. The options being passed into here depends on whether you're doing a prod build or a dev build. Since we want to build the client bundle and the prerendering server bundle, let's take a look at https://github./webpack/react-starter/blob/master/webpack-production.config.js. It's creating two bundles, specifically the first one with separate stylesheets targetted for browser, and the second config is for prerendering.

For the first pilation, it uses this:

plugins.push(new ExtractTextPlugin("[name].css" + (options.longTermCaching ? "?[contenthash]" : "")));

to create a separate css file alongside your bundle. During the second pilation (for prerendering), it uses null-loader to load the styles (because we already have the styles we needed in a css file, we can just use that).

Now here's where we inject the path to css into your server template. Take a look here at a simplified server.js: https://github./webpack/react-starter/blob/8e6971d8fc9d18eeef7818bd6e9be45f6b8643e6/lib/server.js

var STYLE_URL = "main.css?" + stats.hash;
var SCRIPT_URL = [].concat(stats.assetsByChunkName.main)[0];
app.get("/*", function(req, res) {
    res.contentType = "text/html; charset=utf8";
    res.end(prerenderApplication(SCRIPT_URL, STYLE_URL, COMMONS_URL));
});

Assuming your output path for your bundle is the same as server.js (otherwise you can get the publicPath using require("../build/stats.json").publicPath and prepend it to your STYLE_URL and SCRIPT_URL above.

Then in your prerender.jsx: https://github./webpack/react-starter/blob/8e6971d8fc9d18eeef7818bd6e9be45f6b8643e6/config/prerender.jsx Grab your server-side template prerender.html and replace the URLs:

var html = require("../app/prerender.html");
module.exports = function(scriptUrl, styleUrl, monsUrl) {
    var application = React.renderComponentToString(<Application />);
    return html.replace("STYLE_URL", styleUrl).replace("SCRIPT_URL", scriptUrl).replace("COMMONS_URL", monsUrl).replace("CONTENT", application);
};

I admit this can be plicated and confusing, and if it's easier to use a separate gulpfile go for it. But do play around with this. If you need more clarification and help, you can post a ment and I'll get to it as soon as I can or you can use the webpack chatroom here (https://gitter.im/webpack/webpack), I'm sure one of the developers there can probably give you a better explanation than I did.

Hope this is somewhat(?) helpful!

The initial flash appears because "style-loader" hasn't yet downloaded your CSS styles.

To resolve this issue, isomorphic (universal) rendering is required (markup generation on server, and not just in production mode - in development mode too).

You can achieve isomorphic rendering either by following the "react-starter" project path (mentioned in the ment above), or by using webpack-isomorphic-tools

https://github./halt-hammerzeit/webpack-isomorphic-tools

You will need 2 webpack builds: 1 for web, 1 for node.

If you remove style, you will be able to load your stylesheet on both the server and client.

  var css = require("!css!sass!../../../styles/main.scss");

Since you aren't using the style-loader anymore, you will need to manually inject the resulting css into your view.

In your view you will need to include this

<style>{css.toString()}</style>

That should work on both server and client. When you do React.renderToString(), the css will be parsed in whatever order it is in your html. If it is at the top/in the <head>, there should be no flicker.

发布评论

评论列表(0)

  1. 暂无评论