├── .gitignore ├── LICENSE ├── README.md ├── TODO.md ├── bower_components └── normalize.scss │ ├── .bower.json │ ├── .gitignore │ ├── README.md │ └── _normalize.scss ├── client ├── app.jsx ├── app.scss └── count.jsx ├── gulpfile.js ├── package.json ├── server ├── app.js ├── demo.js └── index.html └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript 29 | bower_components 30 | .sass-cache 31 | build -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kiran Abburi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-isomorphic-example 2 | This is an experimental example for react isomorphic applications. 3 | It uses express, reactjs, react-router, webpack, gulp. 4 | 5 | As of now, this example has simple [demo page](http://webrafter.com/opensource/react-isomorphic-example) 6 | 7 | Features to be added 8 | * Multiple routes 9 | * Forms 10 | * Async data loading 11 | * And more 12 | 13 | Other available example 14 | * https://github.com/insin/isomorphic-lab 15 | * https://github.com/DeTeam/webpack-node-react-example -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | * including styles on server-side not working -------------------------------------------------------------------------------- /bower_components/normalize.scss/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "normalize.scss", 3 | "homepage": "https://github.com/kristerkari/normalize.scss", 4 | "_release": "dda8697c44", 5 | "_resolution": { 6 | "type": "branch", 7 | "branch": "master", 8 | "commit": "dda8697c44b0c5d94ed9b17c6349d6b232672f55" 9 | }, 10 | "_source": "https://github.com/kristerkari/normalize.scss.git", 11 | "_target": "*", 12 | "_originalSource": "https://github.com/kristerkari/normalize.scss.git", 13 | "_direct": true 14 | } -------------------------------------------------------------------------------- /bower_components/normalize.scss/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # OS generated files # 30 | ###################### 31 | .DS_Store* 32 | ehthumbs.db 33 | Icon? 34 | Thumbs.db -------------------------------------------------------------------------------- /bower_components/normalize.scss/README.md: -------------------------------------------------------------------------------- 1 | normalize.css 2 | ============= 3 | 4 | Normalize.css is a customisable CSS file that makes browsers render all elements more consistently and in line with modern standards. We researched the differences between default browser styles in order to precisely target only the styles that need normalizing. 5 | 6 | [Check out the demo](http://necolas.github.com/normalize.css/demo.html) 7 | 8 | What does it do? 9 | ----------- 10 | 11 | * Preserves useful defaults, unlike many CSS resets. 12 | * Normalizes styles for a wide range of elements. 13 | * Corrects bugs and common browser inconsistencies. 14 | * Improves usability with subtle improvements. 15 | * Explains what code does using detailed comments. 16 | 17 | How to use it 18 | ----------- 19 | 20 | Normalize.css is intended to be used as an alternative to CSS resets. 21 | 22 | It is suggested that you read through the `normalize.css` file and customise it to meet the design requirements of a project rather including it as a "black box". 23 | 24 | If you prefer to use a different CSS formatting style, consider using a tool like [Procssor](http://procssor.com/). 25 | 26 | If you would like to minify the file, you can use a tool like this [online CSS compressor using YUI Compressor](http://www.refresh-sf.com/yui/) or perform the minification as part of your build process. 27 | 28 | Browser support 29 | ----------- 30 | 31 | * Google Chrome 32 | * Mozilla Firefox 3+ 33 | * Apple Safari 4+ 34 | * Opera 10+ 35 | * Internet Explorer 6+ 36 | 37 | Contribute 38 | ----------- 39 | 40 | Please read the Wiki entry on [contributing to Normalize.css](https://github.com/necolas/normalize.css/wiki/contribute) 41 | 42 | License 43 | ----------- 44 | 45 | Public domain 46 | 47 | Acknowledgements 48 | ------------ 49 | 50 | Normalize.css is a project by [Nicolas Gallagher](http://github.com/necolas) and [Jonathan Neal](http://github.com/jonathantneal). -------------------------------------------------------------------------------- /bower_components/normalize.scss/_normalize.scss: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // Normalize.scss based on Nicolas Gallagher and Jonathan Neal's 3 | // normalize.css v2.1.3 | MIT License | git.io/normalize 4 | // ============================================================================= 5 | 6 | // ============================================================================= 7 | // Normalize.scss settings 8 | // ============================================================================= 9 | 10 | 11 | // Set to true if you want to add support for IE6 and IE7 12 | // Notice: setting to true might render some elements 13 | // slightly differently than when set to false 14 | $legacy_support_for_ie: false !default; // Used also in Compass 15 | 16 | 17 | // Set the default font family here so you don't have to override it later 18 | $normalized_font_family: sans-serif !default; 19 | 20 | $normalize_headings: true !default; 21 | 22 | $h1_font_size: 2em !default; 23 | $h2_font_size: 1.5em !default; 24 | $h3_font_size: 1.17em !default; 25 | $h4_font_size: 1em !default; 26 | $h5_font_size: 0.83em !default; 27 | $h6_font_size: 0.75em !default; 28 | 29 | $h1_margin: 0.67em 0 !default; 30 | $h2_margin: 0.83em 0 !default; 31 | $h3_margin: 1em 0 !default; 32 | $h4_margin: 1.33em 0 !default; 33 | $h5_margin: 1.67em 0 !default; 34 | $h6_margin: 2.33em 0 !default; 35 | 36 | $background: #fff !default; 37 | $color: #000 !default; 38 | 39 | // ============================================================================= 40 | // HTML5 display definitions 41 | // ============================================================================= 42 | 43 | // Corrects block display not defined in IE6/7/8/9 & FF3 44 | 45 | article, 46 | aside, 47 | details, 48 | figcaption, 49 | figure, 50 | footer, 51 | header, 52 | hgroup, 53 | nav, 54 | section, 55 | summary { 56 | display: block; 57 | } 58 | 59 | // Corrects inline-block display not defined in IE6/7/8/9 & FF3 60 | 61 | audio, 62 | canvas, 63 | video { 64 | display: inline-block; 65 | @if $legacy_support_for_ie { 66 | *display: inline; 67 | *zoom: 1; 68 | } 69 | } 70 | 71 | // 1. Prevents modern browsers from displaying 'audio' without controls 72 | // 2. Remove excess height in iOS5 devices 73 | 74 | audio:not([controls]) { 75 | display: none; // 1 76 | height: 0; // 2 77 | } 78 | 79 | // 80 | // Address `[hidden]` styling not present in IE 8/9. 81 | // Hide the `template` element in IE, Safari, and Firefox < 22. 82 | // 83 | 84 | [hidden], template { 85 | display: none; 86 | } 87 | 88 | // ============================================================================= 89 | // Base 90 | // ============================================================================= 91 | 92 | // 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units 93 | // http://clagnut.com/blog/348/#c790 94 | // 2. Prevents iOS text size adjust after orientation change, without disabling user zoom 95 | // www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/ 96 | 97 | html { 98 | @if $legacy_support_for_ie { 99 | font-size: 100%; // 1 100 | } 101 | background: $background; 102 | color: $color; 103 | -webkit-text-size-adjust: 100%; // 2 104 | -ms-text-size-adjust: 100%; // 2 105 | } 106 | 107 | // Addresses font-family inconsistency between 'textarea' and other form elements. 108 | 109 | html, 110 | button, 111 | input, 112 | select, 113 | textarea { 114 | font-family: $normalized_font_family; 115 | } 116 | 117 | // Addresses margins handled incorrectly in IE6/7 118 | 119 | body { 120 | margin: 0; 121 | } 122 | 123 | // ============================================================================= 124 | // Links 125 | // ============================================================================= 126 | 127 | // 1. Remove the gray background color from active links in IE 10. 128 | // 2. Addresses outline displayed oddly in Chrome 129 | // 3. Improves readability when focused and also mouse hovered in all browsers 130 | // people.opera.com/patrickl/experiments/keyboard/test 131 | 132 | a { 133 | // 1 134 | 135 | background: transparent; 136 | 137 | // 2 138 | 139 | &:focus { 140 | outline: thin dotted; 141 | } 142 | 143 | // 3 144 | 145 | &:hover, 146 | &:active { 147 | outline: 0; 148 | } 149 | } 150 | 151 | // ============================================================================= 152 | // Typography 153 | // ============================================================================= 154 | 155 | // Addresses font sizes and margins set differently in IE6/7 156 | // Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5 157 | 158 | @if $normalize_headings == true { 159 | h1 { 160 | font-size: $h1_font_size; 161 | margin: $h1_margin; 162 | } 163 | 164 | h2 { 165 | font-size: $h2_font_size; 166 | margin: $h2_margin; 167 | } 168 | 169 | h3 { 170 | font-size: $h3_font_size; 171 | margin: $h3_margin; 172 | } 173 | 174 | h4 { 175 | font-size: $h4_font_size; 176 | margin: $h4_margin; 177 | } 178 | 179 | h5 { 180 | font-size: $h5_font_size; 181 | margin: $h5_margin; 182 | } 183 | 184 | h6 { 185 | font-size: $h6_font_size; 186 | margin: $h6_margin; 187 | } 188 | } 189 | 190 | // Addresses styling not present in IE 8/9, S5, Chrome 191 | 192 | abbr[title] { 193 | border-bottom: 1px dotted; 194 | } 195 | 196 | // Addresses style set to 'bolder' in FF3+, S4/5, Chrome 197 | 198 | b, 199 | strong { 200 | font-weight: bold; 201 | } 202 | 203 | @if $legacy_support_for_ie { 204 | blockquote { 205 | margin: 1em 40px; 206 | } 207 | } 208 | 209 | // Addresses styling not present in S5, Chrome 210 | 211 | dfn { 212 | font-style: italic; 213 | } 214 | 215 | // Addresses styling not present in IE6/7/8/9 216 | 217 | mark { 218 | background: #ff0; 219 | color: #000; 220 | } 221 | 222 | // Addresses margins set differently in IE6/7 223 | @if $legacy_support_for_ie { 224 | p, 225 | pre { 226 | margin: 1em 0; 227 | } 228 | } 229 | 230 | // Corrects font family set oddly in IE6, S4/5, Chrome 231 | // en.wikipedia.org/wiki/User:Davidgothberg/Test59 232 | 233 | code, 234 | kbd, 235 | pre, 236 | samp { 237 | font-family: monospace, serif; 238 | @if $legacy_support_for_ie { 239 | _font-family: 'courier new', monospace; 240 | } 241 | font-size: 1em; 242 | } 243 | 244 | // Improves readability of pre-formatted text in all browsers 245 | 246 | pre { 247 | white-space: pre; 248 | white-space: pre-wrap; 249 | word-wrap: break-word; 250 | } 251 | 252 | // Set consistent quote types. 253 | 254 | q { 255 | quotes: "\201C" "\201D" "\2018" "\2019"; 256 | } 257 | 258 | // 1. Addresses CSS quotes not supported in IE6/7 259 | // 2. Addresses quote property not supported in S4 260 | 261 | // 1 262 | @if $legacy_support_for_ie { 263 | q { 264 | quotes: none; 265 | } 266 | } 267 | 268 | // 2 269 | q { 270 | &:before, 271 | &:after { 272 | content: ''; 273 | content: none; 274 | } 275 | } 276 | 277 | // Address inconsistent and variable font size in all browsers. 278 | 279 | small { 280 | font-size: 80%; 281 | } 282 | 283 | // Prevents sub and sup affecting line-height in all browsers 284 | // gist.github.com/413930 285 | 286 | sub, 287 | sup { 288 | font-size: 75%; 289 | line-height: 0; 290 | position: relative; 291 | vertical-align: baseline; 292 | } 293 | 294 | sup { 295 | top: -0.5em; 296 | } 297 | 298 | sub { 299 | bottom: -0.25em; 300 | } 301 | 302 | // ============================================================================= 303 | // Lists 304 | // ============================================================================= 305 | 306 | // Addresses margins set differently in IE6/7 307 | @if $legacy_support_for_ie { 308 | dl, 309 | menu, 310 | ol, 311 | ul { 312 | margin: 1em 0; 313 | } 314 | } 315 | 316 | @if $legacy_support_for_ie { 317 | dd { 318 | margin: 0 0 0 40px; 319 | } 320 | } 321 | 322 | // Addresses paddings set differently in IE6/7 323 | @if $legacy_support_for_ie { 324 | menu, 325 | ol, 326 | ul { 327 | padding: 0 0 0 40px; 328 | } 329 | } 330 | 331 | // Corrects list images handled incorrectly in IE7 332 | 333 | nav { 334 | ul, 335 | ol { 336 | @if $legacy_support_for_ie { 337 | list-style-image: none; 338 | } 339 | } 340 | } 341 | 342 | // ============================================================================= 343 | // Embedded content 344 | // ============================================================================= 345 | 346 | // 1. Removes border when inside 'a' element in IE6/7/8/9, FF3 347 | // 2. Improves image quality when scaled in IE7 348 | // code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ 349 | 350 | img { 351 | border: 0; // 1 352 | @if $legacy_support_for_ie { 353 | -ms-interpolation-mode: bicubic; // 2 354 | } 355 | } 356 | 357 | // Corrects overflow displayed oddly in IE9 358 | 359 | svg:not(:root) { 360 | overflow: hidden; 361 | } 362 | 363 | // ============================================================================= 364 | // Figures 365 | // ============================================================================= 366 | 367 | // Addresses margin not present in IE6/7/8/9, S5, O11 368 | 369 | figure { 370 | margin: 0; 371 | } 372 | 373 | // ============================================================================= 374 | // Forms 375 | // ============================================================================= 376 | 377 | // Corrects margin displayed oddly in IE6/7 378 | @if $legacy_support_for_ie { 379 | form { 380 | margin: 0; 381 | } 382 | } 383 | 384 | // Define consistent border, margin, and padding 385 | 386 | fieldset { 387 | border: 1px solid #c0c0c0; 388 | margin: 0 2px; 389 | padding: 0.35em 0.625em 0.75em; 390 | } 391 | 392 | // 1. Corrects color not being inherited in IE6/7/8/9 393 | // 2. Remove padding so people aren't caught out if they zero out fieldsets. 394 | // 3. Corrects text not wrapping in FF3 395 | // 4. Corrects alignment displayed oddly in IE6/7 396 | 397 | legend { 398 | border: 0; // 1 399 | padding: 0; // 2 400 | white-space: normal; // 3 401 | @if $legacy_support_for_ie { 402 | *margin-left: -7px; // 4 403 | } 404 | } 405 | 406 | // 1. Correct font family not being inherited in all browsers. 407 | // 2. Corrects font size not being inherited in all browsers 408 | // 3. Addresses margins set differently in IE6/7, FF3+, S5, Chrome 409 | // 4. Improves appearance and consistency in all browsers 410 | 411 | button, 412 | input, 413 | select, 414 | textarea { 415 | font-family: inherit; // 1 416 | font-size: 100%; // 2 417 | margin: 0; // 3 418 | vertical-align: baseline; // 4 419 | @if $legacy_support_for_ie { 420 | *vertical-align: middle; // 4 421 | } 422 | } 423 | 424 | // Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet 425 | 426 | button, input { 427 | line-height: normal; 428 | } 429 | 430 | // Address inconsistent `text-transform` inheritance for `button` and `select`. 431 | // All other form control elements do not inherit `text-transform` values. 432 | // Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. 433 | // Correct `select` style inheritance in Firefox 4+ and Opera. 434 | 435 | button, 436 | select { 437 | text-transform: none; 438 | } 439 | 440 | // 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 441 | // and `video` controls 442 | // 2. Corrects inability to style clickable 'input' types in iOS 443 | // 3. Improves usability and consistency of cursor style between image-type 444 | // 'input' and others 445 | // 4. Removes inner spacing in IE7 without affecting normal text inputs 446 | // Known issue: inner spacing remains in IE6 447 | 448 | button, 449 | html input[type="button"], // 1 450 | input[type="reset"], 451 | input[type="submit"] { 452 | -webkit-appearance: button; // 2 453 | cursor: pointer; // 3 454 | @if $legacy_support_for_ie { 455 | *overflow: visible; // 4 456 | } 457 | } 458 | 459 | // Re-set default cursor for disabled elements 460 | 461 | button[disabled], 462 | input[disabled] { 463 | cursor: default; 464 | } 465 | 466 | // Removes inner padding and border in FF3+ 467 | // www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/ 468 | 469 | button, input { 470 | &::-moz-focus-inner { 471 | border: 0; 472 | padding: 0; 473 | } 474 | } 475 | 476 | // 1. Removes default vertical scrollbar in IE6/7/8/9 477 | // 2. Improves readability and alignment in all browsers 478 | 479 | textarea { 480 | overflow: auto; // 1 481 | vertical-align: top; // 2 482 | } 483 | 484 | // ============================================================================= 485 | // Tables 486 | // ============================================================================= 487 | 488 | // Remove most spacing between table cells 489 | 490 | table { 491 | border-collapse: collapse; 492 | border-spacing: 0; 493 | } 494 | 495 | input { 496 | // 1. Addresses appearance set to searchfield in S5, Chrome 497 | // 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof) 498 | &[type="search"] { 499 | -webkit-appearance: textfield; // 1 500 | -moz-box-sizing: content-box; 501 | -webkit-box-sizing: content-box; // 2 502 | box-sizing: content-box; 503 | 504 | // Remove inner padding and search cancel button in Safari 5 and Chrome 505 | // on OS X. 506 | &::-webkit-search-cancel-button, 507 | &::-webkit-search-decoration { 508 | -webkit-appearance: none; 509 | } 510 | } 511 | 512 | // 1. Address box sizing set to `content-box` in IE 8/9/10. 513 | // 2. Remove excess padding in IE 8/9/10. 514 | // 3. Removes excess padding in IE7 515 | // Known issue: excess padding remains in IE6 516 | &[type="checkbox"], 517 | &[type="radio"] { 518 | box-sizing: border-box; // 1 519 | padding: 0; // 2 520 | @if $legacy_support_for_ie { 521 | *height: 13px; // 3 522 | *width: 13px; // 3 523 | } 524 | } 525 | } 526 | -------------------------------------------------------------------------------- /client/app.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ExecutionEnvironment = require('react/lib/ExecutionEnvironment'); 3 | 4 | var App = React.createClass({ 5 | getInitialState: function () { 6 | return { show: false} 7 | }, 8 | toggle: function () { 9 | this.setState({ 10 | show: !this.state.show 11 | }) 12 | }, 13 | render: function () { 14 | var message = null; 15 | if (this.state.show) { 16 | message =

You are seeing this message because application got bootstraped properly on client. So client side interactions are working

; 17 | } 18 | return ( 19 |
20 |
21 | React Isomorphic Example 22 |
23 |
24 |

This is demo of react-isomorphic-example

25 |

You can view page source and see html tags with "data-reactid" attibutes. This indicates that page is initially rendered on server

26 |

For Example:

27 |

{'

React Isomorphic Example
'}

28 |

After javascript is loaded, reactjs picks up on client side to provide interactivity

29 |
30 | {(this.state.show? 'Hide': 'Show') + ' Message'} 31 |
32 |
{message}
33 |
34 |
35 | ); 36 | } 37 | }) 38 | 39 | if (ExecutionEnvironment.canUseDOM) { 40 | document.addEventListener('DOMContentLoaded', function () { 41 | React.render(React.createElement(App), document.body); 42 | }); 43 | } else { 44 | module.exports = React.renderToString(React.createElement(App)); 45 | } 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /client/app.scss: -------------------------------------------------------------------------------- 1 | 2 | 3 | // body { 4 | // display: flex; 5 | // justify-content: center; 6 | // width: 100%; 7 | // } 8 | 9 | // .container { 10 | // display: flex; 11 | // flex-direction: column; 12 | // width: 80%; 13 | // } 14 | 15 | // .header { 16 | // color: white; 17 | // background: #004876; 18 | // padding: 20px; 19 | // font-size: 24px; 20 | // } -------------------------------------------------------------------------------- /client/count.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | 3 | var Count = React.createClass({ 4 | getInitialState: function () { 5 | return {count: 1} 6 | }, 7 | incr: function () { 8 | this.setState({count: this.state.count + 1}); 9 | }, 10 | render: function () { 11 | return ( 12 |
13 | 14 |

{this.state.count}

15 |
16 | ); 17 | } 18 | }) 19 | 20 | module.exports = Count; -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var gutil = require('gulp-util'); 3 | var del = require('del'); 4 | var sass = require('gulp-sass'); 5 | var webpack = require('webpack'); 6 | var WebpackDevServer = require('webpack-dev-server'); 7 | 8 | gulp.task('clean', function () { 9 | del('./build/*', function () { 10 | console.log('cleaning done'); 11 | }); 12 | }); 13 | 14 | gulp.task('sass', function () { 15 | return gulp.src(['./client/**/*.{scss,sass}']) 16 | .pipe(sass({ includePaths : ['bower_components', 'node_modules'], errLogToConsole: true})) 17 | .pipe(gulp.dest('./build')); 18 | }); 19 | 20 | // gulp.task('webpack', function (callback) { 21 | // var myConfig = require('./webpack.config.js'); 22 | // var webpackCompiler = webpack(myConfig, function(err, stats) { 23 | // if(err) throw new gutil.PluginError("webpack:build", err); 24 | // gutil.log("[webpack:build]", stats.toString({ 25 | // colors: true 26 | // })); 27 | // callback(); 28 | // }); 29 | // }); 30 | 31 | gulp.task('watch', ['sass'], function () { 32 | gulp.watch(['./client/**/*.{scss,sass}'], ['sass']); 33 | // gulp.watch(['./client/**/*.{js,jsx}'], ['webpack']); 34 | }); 35 | 36 | 37 | // gulp.task('server', function (callback) { 38 | // var myConfig = require('./webpack.config.js'); 39 | // var webpackCompiler = webpack(myConfig, function(err, stats) { 40 | // }); 41 | 42 | // new WebpackDevServer(webpackCompiler, { 43 | // contentBase: './build', 44 | // hot: true, 45 | // debug: true 46 | // }).listen(4000, 'localhost', function (err, result) { 47 | // }); 48 | // }); 49 | 50 | gulp.task('default', ['watch']); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-isomorphic-example", 3 | "version": "0.1.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "./node_modules/.bin/nodemon server/app.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/akiran/react-isomorphic-example" 12 | }, 13 | "author": "", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/akiran/react-isomorphic-example/issues" 17 | }, 18 | "homepage": "https://github.com/akiran/react-isomorphic-example", 19 | "dependencies": { 20 | "autoprefixer-core": "^5.0.0", 21 | "css-loader": "^0.9.1", 22 | "enhanced-require": "^0.5.0-beta6", 23 | "express": "^4.11.1", 24 | "jade": "^1.9.1", 25 | "lodash": "^2.4.1", 26 | "object-assign": "^2.0.0", 27 | "postcss-loader": "^0.3.0", 28 | "react": "^0.12.2", 29 | "sass-loader": "^0.3.1", 30 | "style-loader": "^0.8.3" 31 | }, 32 | "devDependencies": { 33 | "6to5": "^2.13.7", 34 | "6to5-loader": "^2.0.0", 35 | "del": "^1.1.1", 36 | "expose-loader": "^0.6.0", 37 | "gulp": "^3.8.10", 38 | "gulp-sass": "^1.3.2", 39 | "gulp-util": "^3.0.2", 40 | "jsx-loader": "^0.12.2", 41 | "webpack": "^1.5.1", 42 | "webpack-dev-middleware": "^1.0.11", 43 | "webpack-dev-server": "^1.7.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var webpack = require('webpack'); 3 | var webpackMiddleware = require('webpack-dev-middleware'); 4 | var webpackConfig = require('../webpack.config.js'); 5 | var path =require('path'); 6 | 7 | var app = express(); 8 | app.use(express.static(path.join(__dirname, '../build'))); 9 | 10 | app.use(webpackMiddleware(webpack(webpackConfig), { 11 | })); 12 | 13 | app.use('/', require('./demo')); 14 | 15 | app.listen('8000'); -------------------------------------------------------------------------------- /server/demo.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var webpackConfig = require('../webpack.config.js'); 4 | var assign = require('object-assign'); 5 | var _ = require('lodash'); 6 | var fs = require('fs'); 7 | var path = require('path'); 8 | 9 | var requireConfig = assign({}, webpackConfig, { 10 | recursive: true, 11 | // hot: true, 12 | }); 13 | var webpackRequire = require("enhanced-require")(module, requireConfig); 14 | 15 | var content = webpackRequire("../client/app"); 16 | var template = fs.readFileSync(path.join(__dirname, 'index.html'), 'utf8'); 17 | var jsPath = process.env.NODE_ENV === 'production' ? 'http://static.webrafter.com' : ''; 18 | jsPath += '/react-isomorphic-example.js'; 19 | 20 | router.get('/', function (req, res) { 21 | var html = _.template(template, {content: content, jsPath: jsPath}); 22 | res.status(200).send(html); 23 | }); 24 | 25 | module.exports = router; -------------------------------------------------------------------------------- /server/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React Isomorphic example 8 | 9 | 10 | 11 | 12 | 13 | <%= content %> 14 | 15 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | var autoprefixer = require('autoprefixer-core'); 4 | 5 | module.exports = { 6 | entry: { 7 | 'react-isomorphic-example.js': './client/app.jsx' 8 | // 'app.js': './client/app.jsx' 9 | }, 10 | output: { 11 | path: path.join(__dirname, 'build'), 12 | filename: '[name]', 13 | }, 14 | module: { 15 | loaders: [ 16 | {test: /\.jsx$/, loaders: ['jsx?harmony']}, 17 | { 18 | test: /\.scss$/, 19 | loader: "style!css!sass?outputStyle=expanded&" + 20 | "includePaths[]=" + 21 | (path.resolve(__dirname, "./bower_components")) + "&" + 22 | "includePaths[]=" + 23 | (path.resolve(__dirname, "./node_modules")) 24 | }, 25 | ], 26 | }, 27 | // postcss: [ autoprefixer({ browsers: ['last 2 version'] }) ], 28 | resolve : { 29 | alias: { 30 | 31 | }, 32 | extensions: ['', '.js', '.jsx'] 33 | }, 34 | plugins: [ 35 | ] 36 | }; --------------------------------------------------------------------------------