As a thought exercise, I've been trying to create a blogging application using Isomorphic React. After some google searching I've come across these three tutorials:
Medium: A Modern Isomorphic stack:
https://medium.com/#MoBinni/a-modern-isomorphic-stack-6609c7c9d057
blog.lunarlogic.org: How to create a universal Reactjs application
http://blog.lunarlogic.io/2015/how-to-create-a-universal-reactjs-application-with-bare-reactjs/
One part that I'm confused in particular is with how the html-webpack-plugin works on the server side.
Both of these tutorials have templates that look like:
<html>
<head>
...
</head>
<body>
...
<%- reactOutput %>
</body>
</html>
However, when I try to run this template through webpack, I get errors that reactOutput is undefined.
On a pure client-side app, I would use html-webpack-plugin to generate my index.html file to be served to the clients. This generation would make it easier for me because I have different configurations in webpack for dev and production. (Common chunks and all of that)
Do I even need to consider that when talking about server side rendering? Or am I going about this all wrong?
I dont think html-webpack-plugin figures in the equation, except to pre-generate the template.
Once you have the template content you provide it to the renderer along with the value of reactOutput.
You make a call like shown here in line 42 to grab the rendered content:
var reactOutput = ReactDOMServer.renderToString(<RoutingContext {...renderProps} />);
Then you will be giving this var along with the template. In the tutorial they use ejs for templating though you can plug in your own:
res.render('index', {
reactOutput: reactOutput)
});
Related
I have a vue.js/Phoenix app. I'm trying to understand how to properly configure the frontend assets. I'm having trouble understanding why my priv/static/js/app.js file keeps updating whenever I Change something in other files. I'm trying to research this behavior but I can't seem to find out any information.
app.html.eex
<body>
<%= render #view_module, #view_template, assigns %>
<script src="<%= static_path(#conn, "/js/app.js") %>"></script>
</body>
My basic question is how to structure a vue.js app? The fact that I change something in asset/src dynamically changes something in static/js/app.js seems really strange. Does anybody have resources or answers on what might be happening here or places I can go to learn more?
In addition to what Pawel said, this behaviour might be intentionally configured. There is the watcher specified in config/dev.exs:
watchers: [
node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
cd: Path.expand("../assets", __DIR__)]]
That would be used in development mode to allow so-called “hot reload”: one does not need to reload the application when some changes in assets are made, app.js will be rebuilt and reloaded automagically.
There is also assets/brunch-config.js file, where one might specify rules of how the resulting app.js is being produced. By default is just compiles everything found in assets to the single javascript file, but this behaviour might be easily changed (e.g. one might exclude anything from being built into app.js and specify their own rules to provide an access to these excluded files.)
As contrary as this might sound, this is exactly the behaviour Phoenix (with Brunch) provides.
The main idea is to implement your JS functionality in assets/js/app.js, then Brunch (http://brunch.io/) as a build tool will take the content, compile/transpile and output to priv/static/js/app.js.
This means, with default configuration that comes with Phoenix, you can use ES6 in your code in assets/js/app.js, but this will be "translated" to executable form (that's understood by browsers), and located in priv/. priv/static is exposed publicly, and this will be the content available by:
<script src="<%= static_path(#conn, "/js/app.js") %>"></script>
To wrap up.
Code in priv/static is not meant to be changed by code, it gets there automatically by changes you put under your source control in assets/.
If that's any help, you can take a look at one of old blog posts about assets in Phoenix here.
Good luck!
I have been happy using webpack with Vue as of now. It uses a similar, configurable, watcher as the one mentioned by mudasobwa. In Webpack if you touch a file that is in part of the bundle it will recompile the needed files only (which can still be many depending on the dependency graph), probably brunch recompiles all.
I also use Yarn to manage npm, and I always include vuex unless it's really something just basic (although not related to file organisation it does help a lot organising vue on any non-trivial apps). Then
/assets
js
entry point files that I use for webpack output into its own individual bundles/apps
folders to organise these, usually /components-views-related, /store-related, /shared-utilities
css
.scss files, divided so that they can be split into "global" styles and individual styles that then are required in each "entry point". Then I use a "general" scss stylesheet on "all pages" and each page the corresponding css bundle where they're needed.
Then on the templates side, I wrote a small, overly complex, brittle, system to just automate the "bundle" that gets loaded on the template (in the html document head) but you can just load each bundle/s where you need them.
I am creating a small-to-medium sized data-driven HTML site from developers for developers in our company. The idea is to have a node.js v0.12+ / express v4+ server running which provides some helper functions to access a large database.
I would like to allow other developers with minimum effort to pull the repository from Git, create a custom view (which should be a a partial HTML page-body) and commit back, e.g., something like this:
app/
views/
common.view1/
module.html
module.js
common.view2/
team1.view2/
...
common/
header.html
footer.html
main.html (automatically finds files under views)
What I am looking for is a proven, non-hackish solution or module (e.g., >1k stars on Github) so that with minimal code would allow me to do something like this in my node's app.js:
xxx.templatify('*.html');
xxx.registerFunction('helper', returnString);
expressApp.usetemplateengine(xxx);
And in views/<someview>/module.html:
<% include('common/header'); %>
<h2>Hello <% helper('world'); %> h2>
I wouldn't mind if the include could be defined server-side. The modules.html should however stay vanilla HTML as much as possible.
My question: How can I do this and is there an obvious standard solution I am missing?
I looked a little into ejs, jade and friends, but most seem to impose their own completely new syntax (e.g, Jade), or I would have to register every file individually.
Handlebars is the closest I can think of that closely resembles html, but you will still need to map routes to .handlebars files. Thinking out aloud, you could build a mapping helper method to do that for you, but I have not tried that approach as of to date.
I am working on an isomorphic javascript app with express + react. We started out using jade for server side templates for static content, but combining the two is quickly becoming unwieldy. We have ended up with something like this:
In the express routes:
router.get("/", function(req, res) {
var webpackStats = require('../../config/webpack-stats.json');
var reactHtml = React.renderToString(HiwApp({}));
var slideshowHtml = React.renderToString(slideshowApp({}));
var config = {
webpackStats: webpackStats,
reactOutput: reactHtml,
slideshowHtml: slideshowHtml
};
res.render("how_it_works/howitworks", config);
});
In Jade:
body
.company-logo.center
#react-main-mount
!= reactOutput
include ./content_block_1.jade
include ./content_block_2.jade
#slideshow-main-mount
!= slideshowHtml
This is very brittle-if we want jsx then a jade template then more jsx, we have to make sure we get the order right.
My idea is to do it all with jsx. I know there is React.renderToStaticMarkup for this sort of thing, but that doesn't solve the problem of mixing dynamic with static pages.
The big questions: if we decide to do all of this with jsx (say layout.jsx which contains all components), then call React.renderToString(App({});, will this be a major performance hit? If so, is there a better way to do it to easily combine static and dynamic blocks?
Although this may be a tiny bit off topic: We stuck with jade templates.
Basically we wanted the flexibility to use a non-react + flux architecture for areas of the site when and if that need arose. Our site is basically made up of a number of smaller SP apps: Site, UserAccount, Team and Admin.
Why did we do this?
Smaller filesize and overhead for users who are not accessing all sections of the site.
Option to "opt out" of React and flux if and when the need arises.
Simpler, server side authentication.
The way we have done it successfully was to render a JSX shell template (Html.jsx) on the server using React.renderToStaticMarkup() and then send it as the response to every server-side express route request that is meant to deliver some HTML to the browser. Html.jsx is just a shell containing html head information and GA scripts etc. It should contain no layout.
// Html.jsx
render(){
return (
<html>
<head>
// etc.
</head>
<body>
<div
id="app"
dangerouslySetInnerHTML={{__html: this.props.markup}}>
</div>
</body>
<script dangerouslySetInnerHTML={{__html: this.props.state}</script>
<script>
// GA Scripts etc.
</script>
</html>
)
}
Remember it is totally fine and even recommended to use dangerouslySetInnerHTML on the server when hydrating your app.
Dynamic layout should be done with your your isomorphic components through a hierarchy of components based on their state/props configuration. If you happen to be using React Router, then your router will render view handlers based on the routes you provide it so that means you don't need to manage that yourself.
The reason we use this technique is to architecturally separate our "App" which is isomorphic and responds to state from our server-side template shell which is just a delivery mechanism and is effectively boiler plate. We even keep the Html.jsx template amongst all the express components within our app and do not let it mix with the other isomorphic React components.
One of the most helpful resources I found for working out React/isomorphic architecture was https://github.com/yahoo/flux-examples/tree/master/react-router which is where we stole this technique from.
We explored the idea of integrating handlebars as a templating engine for client's devs using our products in the future but decided that it was less complex to write our own DSL in JSX and use some simple parsing routines to parse our HTML-like DSL to JSX by adding things like export default (ES6 module syntax) at the start of the template and then import the template to a rendering component.
You could of course follow that line of thought and use a jade compiler to spit out the template and then add module syntax around that if you think separate jade files are essential. I also noticed this project as well although I have not explored it in anger: https://github.com/jadejs/react-jade.
Disclaimer - I am very new to making web apps, I just went through a few meteor js tutorials over the weekend, it's pretty cool.
I have this project I want to make, which involves embedding tabular data into websites. I want to do this with a iFrame.
I can see how this could be done with meteor, route to a template to render out the html I want, but I'm concerned with performance. Having the whole app load up to just display a few lines of html seems excessive, it certainly doesn't need all the javascript.
The html can be a static file, only changing when the web app user saves a change, it doesn't have to dynamically load every-time somebody sees the embed.
So what I'm really asking is, how can I use meteor js to write a static html file?
What you need is server side rendering (SSR), because you are intending to serve html directly from your meteor server.
Meteor does not support SSR, yet.
While I haven't myself tried to get SSR working in meteor, Arunoda has, ableit some rather severe limitations. Basically you cannot have much reactivity there. This is probably due to the use of fibers on the server. But you said you do not need reactivity anyway in your iframes, so that should not stop you.
You can combine Arunoda's solution with Iron Router's server routes.
Enable the SSR package:
meteor add meteorhacks:ssr
Put your template into the private directory:
<!-- private/embed.html -->
<template name="embed">
<ul>
{{#each posts}}
<li>{{title}}</li>
{{/each}}
</ul>
</template>
On the server, compile it with:
SSR.compileTemplate('embed', Assets.getText('embed.html'));
And declare your template manager:
// server/embed.js
Template.posts.getPosts = function(category) {
return Posts.find({category: category}, {limit: 20});
}
And then add a server-route as follows:
Router.route('/embed/:owner', function () {
var html = SSR.render('embed', {owner: this.params.owner});
this.response.end(html);
}, {where: 'server'});
Now you just need to point your iframe to http://localhost:3000/embed/myusername.
At this stage I would not recommend using meteor in this way, but instead create a simple backend that connects to DDP or mongo directly and renders your iframe's html.
Background: We're in the process of porting an ASP.NET application from traditional WebForms to Web API + Angular. The app is primarily used in countries with poor internet connections, and we've found in practice that latency is a bigger issue than bandwidth. So our priority is to reduce the overall number of requests to the server, even if that means pre-loading scripts or other resources that the user might not ending up needing.
The problem: As we replace WebForms user controls (*.ascx) with Angular directives and templates, the number of little HTML template files is proliferating; so you have to make a lot of server requests for any given view, which is a big problem in a high-latency environment.
One possible approach: I'm thinking of using T4 to combine all templates used by the app into a single file that would look something like this:
myApp.templates = {};
myApp.templates.myFirstDirective = "<div> ... lots of markup here ... </div>"
myApp.templates.mySecondDirective = "<table> ... more markup ... </table>"
This file would then be requested once and cached by the browser, so subsequent page loads wouldn't require any further round trips to the server. The templates would then be available to all directives so that instead of referencing a templateUrl they just pull up the required template like this
return {
link: link,
template: myApp.templates.myFirstDirective,
... etc
}
Question: Is this a good idea? Is there a better or more Angular-native way of combining Angular templates into a single file?
Maybe using the $templateCache-Service is a possibility. Read about it here.
If I understand it right, it's basically what you were already planning, with the difference that you don't need HTML strings in your JavaScript but you can write HTML in .html files (or one big HTML file containing all Templates embedded via an ng-include in your index.html).
You could put them in the page kinda like Ember
<script type="text/ng-template" id="/template.html">
content
</script>
We are leaving those html files as they are during development, but combine them into single .js file (which we then add to our main bundle .js file), when we need an optimized build.
We use https://www.npmjs.com/package/gulp-angular-templatecache - it's literally just a few minutes setup if you already have gulp build.
What I do is define all my templates after my main html body.
Doing this also provides a way to automate the process of building a single file from different directive files
for example:
<!DOCTYPE HTML>
<html>
<head>
<script src="bower_components/angular/angular.js"></script>
</head>
<body ng-app="MyApp">
<my-directive></my-directive>
<script src="app.js"></script>
</body>
</html>
<content>
<script type="text/ng-template" id="template1.html">
<h1>Hello</h1>
</script>
</content>
My app.js:
angular.module('MyApp',[])
.directive('myDirective', function() {
return {
scope:{
},
restrict:'AE',
templateUrl:'template1.html',
replace:false
}
})
This way we can easily keep all the javascript for directive in there own files and html for these directives in there own file
And during build time we can easily merge these files so that we have only two files: index.html and app.js which means only two requests to server.