├── .config └── devel │ └── settings.json ├── .gitignore ├── .jshintignore ├── .jshintrc ├── .meteor ├── .finished-upgraders ├── .gitignore ├── .id ├── packages ├── platforms ├── release └── versions ├── both ├── actions │ ├── error_actions.jsx │ ├── feed_actions.jsx │ └── post_actions.jsx ├── components │ ├── CommentItem │ │ ├── CommentItem.jsx │ │ └── _CommentItem.scss │ ├── CreatePost │ │ ├── CreatePost.jsx │ │ └── _CreatePost.scss │ ├── Feed │ │ ├── FeedContainer.jsx │ │ └── FeedList.jsx │ ├── FeedItem │ │ ├── FeedComments.jsx │ │ ├── FeedItem.jsx │ │ ├── FeedItemFooter.jsx │ │ ├── FeedItemHeader.jsx │ │ └── _FeedItem.scss │ ├── Footer │ │ ├── Footer.html │ │ └── _Footer.scss │ ├── Header │ │ ├── Header.jsx │ │ └── _Header.scss │ └── ParamsExample │ │ ├── ParamsExample.jsx │ │ └── _ParamsExample.scss ├── domains │ ├── errors_domain.jsx │ ├── feed_domain.jsx │ └── posts_domain.jsx ├── models │ ├── comment.js │ ├── post.js │ └── user.js └── pages │ ├── About.html │ ├── Feed.html │ ├── Feed.js │ ├── Home.html │ └── _Feed.scss ├── client ├── _startup.js ├── index.html ├── lib │ ├── accounts_config.js │ ├── blaze_adapter.html │ └── blaze_adapter.js ├── routes.js └── styles │ ├── _components.scss │ ├── _pages.scss │ └── main.scss ├── lib └── mixins │ └── time_format.js ├── makefile ├── readme.md ├── scss.json ├── server ├── _startup.js └── publications │ └── feed.js └── tests └── jasmine ├── client └── unit │ ├── components │ └── ParamsExample_spec.js │ └── spec_helper.js └── server └── integration └── sample ├── spec ├── PlayerSpec.js └── SpecMatchers.js └── src ├── Player.js └── Song.js /.config/devel/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "public": { 3 | "env": "devel" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamBrodzinski/react-ive-meteor/7a4f53bd453dc99ea646d31a9be4c8ffc9573fd4/.gitignore -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | client/compatibility 2 | packages 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // JSHint Meteor Configuration File 3 | // Match the Meteor Style Guide 4 | // 5 | // By @raix with contributions from @aldeed and @awatson1978 6 | // Source https://github.com/raix/Meteor-jshintrc 7 | // 8 | // See http://jshint.com/docs/ for more details 9 | 10 | "maxerr" : 50, // {int} Maximum error before stopping 11 | 12 | // Enforcing 13 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) 14 | "camelcase" : true, // true: Identifiers must be in camelCase 15 | "curly" : true, // true: Require {} for every new block or scope 16 | "eqeqeq" : true, // true: Require triple equals (===) for comparison 17 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() 18 | "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` 19 | "indent" : 2, // {int} Number of spaces to use for indentation 20 | "latedef" : false, // true: Require variables/functions to be defined before being used 21 | "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()` 22 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` 23 | "noempty" : true, // true: Prohibit use of empty blocks 24 | "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) 25 | "plusplus" : false, // true: Prohibit use of `++` & `--` 26 | "quotmark" : false, // Quotation mark consistency: 27 | // false : do nothing (default) 28 | // true : ensure whatever is used is consistent 29 | // "single" : require single quotes 30 | // "double" : require double quotes 31 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) 32 | "unused" : true, // true: Require all defined variables be used 33 | "strict" : false, // true: Requires all functions run in ES5 Strict Mode 34 | "trailing" : true, // true: Prohibit trailing whitespaces 35 | "maxparams" : false, // {int} Max number of formal params allowed per function 36 | "maxdepth" : false, // {int} Max depth of nested blocks (within functions) 37 | "maxstatements" : false, // {int} Max number statements per function 38 | "maxcomplexity" : false, // {int} Max cyclomatic complexity per function 39 | "maxlen" : 80, // {int} Max number of characters per line 40 | 41 | // Relaxing 42 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) 43 | "boss" : false, // true: Tolerate assignments where comparisons would be expected 44 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. 45 | "eqnull" : false, // true: Tolerate use of `== null` 46 | "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) 47 | "esnext" : true, // true: Allow ES.next (ES6) syntax (ex: `const`) 48 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) 49 | // (ex: `for each`, multiple try/catch, function expression…) 50 | "evil" : false, // true: Tolerate use of `eval` and `new Function()` 51 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs 52 | "funcscope" : false, // true: Tolerate defining variables inside control statements" 53 | "globalstrict" : true, // true: Allow global "use strict" (also enables 'strict') 54 | "iterator" : false, // true: Tolerate using the `__iterator__` property 55 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block 56 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings 57 | "laxcomma" : false, // true: Tolerate comma-first style coding 58 | "loopfunc" : false, // true: Tolerate functions being defined in loops 59 | "multistr" : false, // true: Tolerate multi-line strings 60 | "proto" : false, // true: Tolerate using the `__proto__` property 61 | "scripturl" : false, // true: Tolerate script-targeted URLs 62 | "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment 63 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` 64 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation 65 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` 66 | "validthis" : false, // true: Tolerate using this in a non-constructor function 67 | 68 | // Environments 69 | "browser" : true, // Web Browser (window, document, etc) 70 | "couch" : false, // CouchDB 71 | "devel" : true, // Development/debugging (alert, confirm, etc) 72 | "dojo" : false, // Dojo Toolkit 73 | "jquery" : false, // jQuery 74 | "mootools" : false, // MooTools 75 | "node" : false, // Node.js 76 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) 77 | "prototypejs" : false, // Prototype and Scriptaculous 78 | "rhino" : false, // Rhino 79 | "worker" : false, // Web Workers 80 | "wsh" : false, // Windows Scripting Host 81 | "yui" : false, // Yahoo User Interface 82 | //"meteor" : false, // Meteor.js 83 | 84 | // Legacy 85 | "nomen" : false, // true: Prohibit dangling `_` in variables 86 | "onevar" : false, // true: Allow only one `var` statement per function 87 | "passfail" : false, // true: Stop on first error 88 | "white" : false, // true: Check against strict whitespace and indentation rules 89 | 90 | // Custom globals, from http://docs.meteor.com, in the order they appear there 91 | "globals" : { 92 | "Meteor": false, 93 | "DDP": false, 94 | "Session": false, 95 | "Accounts": false, 96 | "Template": false, 97 | "Match": false, 98 | "check": false, 99 | "Deps": false, 100 | "EJSON": false, 101 | "HTTP": false, 102 | "Email": false, 103 | "Assets": false, 104 | "Handlebars": false, // https://github.com/meteor/meteor/wiki/Handlebars 105 | 106 | // Meteor internals 107 | "DDPServer": false, 108 | "global": false, 109 | "Log": false, 110 | "MongoInternals": false, 111 | "process": false, 112 | "WebApp": false, 113 | "WebAppInternals": false, 114 | 115 | // globals useful when creating Meteor packages 116 | "Package": false, 117 | "Npm": false, 118 | "Tinytest": false, 119 | 120 | "React": false, 121 | "ReactMeteor": false, 122 | 123 | // common Meteor packages 124 | "Random": false, 125 | "_": false, // Underscore.js 126 | "$": false, // jQuery 127 | "Router": false, // iron-router 128 | "RouteController": false, // iron-router 129 | 130 | // Meteor Generate 131 | "AppController": false, 132 | "db": false 133 | } 134 | } 135 | 136 | -------------------------------------------------------------------------------- /.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | notices-for-facebook-graph-api-2 9 | -------------------------------------------------------------------------------- /.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /.meteor/.id: -------------------------------------------------------------------------------- 1 | # This file contains a token that is unique to your project. 2 | # Check it into your repository along with the rest of this directory. 3 | # It can be used for purposes such as: 4 | # - ensuring you don't accidentally deploy one app on top of another 5 | # - providing package authors with aggregated statistics 6 | 7 | 1szn02aozzin1lvs9j 8 | -------------------------------------------------------------------------------- /.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # Check this file (and the other files in this directory) into your repository. 3 | # 4 | # 'meteor add' and 'meteor remove' will edit this file for you, 5 | # but you can also edit it by hand. 6 | 7 | meteor-platform 8 | accounts-ui 9 | accounts-password 10 | 11 | meteorhacks:flow-layout 12 | meteorhacks:flow-router 13 | 14 | react 15 | #grigio:babel 16 | 17 | kevohagan:sweetalert 18 | fourseven:scss 19 | matb33:collection-hooks 20 | velocity:html-reporter 21 | sanjo:jasmine 22 | momentjs:moment 23 | -------------------------------------------------------------------------------- /.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.1.0.2 2 | -------------------------------------------------------------------------------- /.meteor/versions: -------------------------------------------------------------------------------- 1 | accounts-base@1.2.0 2 | accounts-password@1.1.1 3 | accounts-ui@1.1.5 4 | accounts-ui-unstyled@1.1.7 5 | amplify@1.0.0 6 | autoupdate@1.2.1 7 | babel-compiler@5.4.7 8 | babel-runtime@0.1.0 9 | base64@1.0.3 10 | binary-heap@1.0.3 11 | blaze@2.1.2 12 | blaze-tools@1.0.3 13 | boilerplate-generator@1.0.3 14 | callback-hook@1.0.3 15 | check@1.0.5 16 | coffeescript@1.0.6 17 | cosmos:browserify@0.1.4 18 | ddp@1.1.0 19 | deps@1.0.7 20 | ejson@1.0.6 21 | email@1.0.6 22 | fastclick@1.0.3 23 | fourseven:scss@3.1.1 24 | geojson-utils@1.0.3 25 | html-tools@1.0.4 26 | htmljs@1.0.4 27 | http@1.1.0 28 | id-map@1.0.3 29 | jquery@1.11.3_2 30 | json@1.0.3 31 | jsx@0.1.0 32 | kevohagan:sweetalert@0.5.0 33 | launch-screen@1.0.2 34 | less@1.0.14 35 | livedata@1.0.13 36 | localstorage@1.0.3 37 | logging@1.0.7 38 | matb33:collection-hooks@0.7.13 39 | meteor@1.1.6 40 | meteor-platform@1.2.2 41 | meteorhacks:flow-layout@1.4.0 42 | meteorhacks:flow-router@1.9.0 43 | minifiers@1.1.5 44 | minimongo@1.0.8 45 | mobile-status-bar@1.0.3 46 | momentjs:moment@2.10.6 47 | mongo@1.1.0 48 | npm-bcrypt@0.7.8_2 49 | observe-sequence@1.0.6 50 | ordered-dict@1.0.3 51 | package-version-parser@3.0.3 52 | practicalmeteor:chai@1.9.2_3 53 | practicalmeteor:loglevel@1.1.0_3 54 | random@1.0.3 55 | react@0.1.0 56 | react-meteor-data@0.1.0 57 | react-runtime@0.13.3 58 | react-runtime-dev@0.13.3 59 | react-runtime-prod@0.13.3 60 | reactive-dict@1.1.0 61 | reactive-var@1.0.5 62 | reload@1.1.3 63 | retry@1.0.3 64 | routepolicy@1.0.5 65 | sanjo:jasmine@0.14.0 66 | sanjo:karma@1.5.1 67 | sanjo:long-running-child-process@1.0.3 68 | sanjo:meteor-files-helpers@1.1.0_6 69 | sanjo:meteor-version@1.0.0 70 | service-configuration@1.0.4 71 | session@1.1.0 72 | sha@1.0.3 73 | spacebars@1.0.6 74 | spacebars-compiler@1.0.6 75 | srp@1.0.3 76 | templating@1.1.1 77 | tracker@1.0.7 78 | ui@1.0.6 79 | underscore@1.0.3 80 | url@1.0.4 81 | velocity:chokidar@1.0.3_1 82 | velocity:core@0.7.1 83 | velocity:html-reporter@0.7.0 84 | velocity:meteor-internals@1.1.0_7 85 | velocity:meteor-stubs@1.1.0 86 | velocity:shim@0.1.0 87 | webapp@1.2.0 88 | webapp-hashing@1.0.3 89 | -------------------------------------------------------------------------------- /both/actions/error_actions.jsx: -------------------------------------------------------------------------------- 1 | /*global ErrorActions:true */ 2 | 3 | ErrorActions = { 4 | needLogin() { 5 | // TODO make an isomorphic/universal error handler 6 | if (Meteor.isClient) { 7 | alert("You must be logged in to do that"); 8 | } 9 | }, 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /both/actions/feed_actions.jsx: -------------------------------------------------------------------------------- 1 | /*global FeedActions:true, FeedDomain */ 2 | 3 | FeedActions = { 4 | incrementPostLimit(amount) { 5 | FeedDomain.handleIncrementPostLimit(amount); 6 | }, 7 | 8 | incrementStepParam() { 9 | FeedDomain.handleIncrementStepParam(); 10 | }, 11 | 12 | createComment(data) { 13 | FeedDomain.handleCreateComment(data); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /both/actions/post_actions.jsx: -------------------------------------------------------------------------------- 1 | /*global PostActions:true, PostsDomain */ 2 | 3 | PostActions = { 4 | createPost(data) { 5 | // handle side effects here like analytics, 6 | // or gather data to pass to domain 7 | PostsDomain.handleCreatePost(data); 8 | }, 9 | 10 | deletePost(docId) { 11 | PostsDomain.handleDeletePost(docId); 12 | }, 13 | 14 | likePost(docId) { 15 | PostsDomain.handleLikePost(docId); 16 | } 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /both/components/CommentItem/CommentItem.jsx: -------------------------------------------------------------------------------- 1 | class CommentItem extends React.Component { 2 | render() { 3 | return ( 4 |
16 | FlowRouter provides a reactive API that will 17 | allows for automatic render updates when the 18 | data changes 19 |
20 | 21 |This page is really *too* simple for React. It would cause more work to do it that way. Blaze offeres a nice way to write HTML and include a few helpers. If your template gets very complex, React offers more organization and easier modularity. The good news is this page is still reactive if you need it to be! =)
8 | 9 |10 | Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. 11 |
12 | 13 |14 | Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. 15 |
16 | 17 |18 | Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. 19 |
20 | 21 |22 | Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. 23 |
24 | 25 |26 | Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. 27 |
28 |Building a realtime backend for React can be difficult. Meteor makes it easy to buld an app with optimistic UI updating and realtime data streaming (view updates as DB records change).
16 | 17 |TL;DR
18 | 19 |This repo aims to be a sandbox that developers can learn how to create React apps with a Meteor backend. We'll have several branches with different ways to architect/use the app (such as a full flux spec).
20 | 21 |Meteor and Flux/Relay overlap quite a bit so the master branch will be the most simple version that beginners can pickup and start running.
22 | 23 |The data fetching layer of this app is based on the Flux and Relay ideas by allowing child components to declare the data field shape they need (coming soon). This data is passed down through props.
24 | 25 |The Meteor Development Group is working on making a deeper and more seamless integration with Meteor and React. Checkout the progress Here. Once this work is finished and released, this repo will be updated to use the official packages instead.
26 | 27 |These cons are on the core roadmap and will be resolved in the near future. However some of those could be blockers for your project.
63 | 64 |curl https://install.meteor.com/ | sh
more infomake dev
or meter --settings '.config/devel/settings.json'
The master branch of this repo (and live example) use a mixture of Meteor's Blaze (handlebars like syntax) templates and React templates. Blaze is ideal for content that has no state and very little helpers. These large pages (like the about example) would be cumbersome to use in JSX.
76 | 77 |In this setup, the router renders 'page' templates which have the sole responsibility of handling static markup and rendering the topmost React components. These Blaze pages don't subscribe to data, that responsibility is for the topmost components. Example Code
78 | 79 |The rendering path looks something like this:
80 | 81 |client/pages/feed.html
templatefeed
template renders FeedList and CreatePost React componentsHowever if your app looks very 'app like' (Spotify, Slack, etc...) and not 'page like', using 100% React views is a better approach. See the full-react
branch (soon) to see how you can render React views in using the React-Router module.
Fetching data with Meteor is quite different than a traditional REST system. Instead of making requests to single resource endpoints, you can subscribe to one or more publications of data. If this data in the database changes, you'll receive the new data in the client (instantly when using Mongo's Oplog). Using the MeteorMixin, this new data is synced with your subscription/state which re-renders your views.
96 | 97 |This new data is sent into a store called Mini-Mongo. It acts like an in memory Mongo database which turns out to be a really convenient way to access store data. Since this is in memory, ops are very fast (basically a key/value lookup). If you were using the PostgreSQL database you would use SQL to query the Mini-PostgreSQL store instead.
98 | 99 |The whole data cycle looks like this:
100 | 101 |New Meteor users can get tripped up in this process by sending too much data to the client, causing slowdown. This project uses a Flux/Realy type system to help prevent over publishing data. Each component specify what fields they need and their grandparent takes care of the actual query. This grandparent pushes down new data through their props. This makes testing very easy as the fetching only happens in one place. This data fetching system is a first draft so it may change some. It's also trying to stay simple by not trying to solve every edge case. We'll have a full flux/Relay branch for a more complex example of this.
113 | 114 |Meteor provides an RPC style method that can be called on the client or on the server (even other non servers with a DDP adapter). You simply write a method on the server and on the client you call Meteor.call('multiply', 2, 5);
. On the server the call would directly return 10
because we have fibers. On the client we can't block so the last argument would be a callback with params error
and response
. You also have access to a few resources inside the method like this.userId
. It will contain the caller's userId if they are authenticated. Meteor uses these methods under the hood for the Authors.insert({name: 'foo'})
calls. However we're using our own model methods to bypass the hard to reason allow/deny rules.
Meteor provides an RPC style method that can be called on the client or on the server (even other non servers with a DDP adapter). You simply write a method on the server and on the client you call Meteor.call('multiply', 2, 5);
. On the server the call would directly return 10
because we have fibers. On the client we can't block so the last argument would be a callback with params error
and response
. You also have access to a few resources inside the method like this.userId
. It will contain the caller's userId if they are authenticated. Meteor uses these methods under the hood for the Authors.insert({name: 'foo'})
calls. However we're using our own model methods to bypass the hard to reason allow/deny rules. The Meteor methods turn out to be pretty good at standing in for a Flux Dispatcher.
The implementation of data models used in this project is just one of many ways to do it. Meteor does not have an ORM or Model layer so you're up to rolling your own or using a package. There are a few nice model packages but they have lots of magic involved. For simplicity i'm using a pattern i've used in several production apps. However to keep code a bit smaller, the inheritance uses __proto__
which is not supported in old IE. You would need a more verbose method to make this work with unsupported (old) browsers. These models also are not full featured like Mongoose or ActiveRecord, but again for simplicity sake these will work just fine.
Meteor doesn't currently have a file based module import system like Browserfy, Webpack, or ES6 modules (though we can import them and expose globally like this example). However i've heard this is coming in the near future. Currently Meteor has a set of rules it uses for loading. Read the full rundown here. client/
folders are only sent to the client and server
folders are only sent to the server. The both
folder will be sent to both client and server.
No one likes typing boilerplate. If this project's folder structure works for you, Meteor Generate can save a lot of time. I'm in the middle of converting my old MVC patterns with Blaze over to Component structured React. This should be on NPM soon but in the mean time keep an eye out on this branch. It creates models, pages, routes, React components with Sass styles, and more.
139 | 140 |In short, trust nothing on the client. Assume everything being passed from the client to server could be a malicious value. Meteor provides utilities to check all inputs to make sure they are the shape and type you expect. This prevents Mongo injections. If they're not the shape/type you expect, reject it and throw an error. 145 | remove the insecure package. It automatically allows full access to insert/update/remove methods. This would be great for a throw away prototype or for learning the very basics but it's a security hazard.
146 | 147 |The autopublish package should also be removed. This will send your entire serverside database to the client and load it into the Mini-Mongo store. Not only is this slow with large data sets but it's a security hazard.
148 | Only send authorized data to the client. It's up to you to verify if a user should be allowed to subscribe to a publication. They can't access it in Mini-Mongo unless you send it to them. You only want to send data down that they are allowed/supposed to use.
Meteor Security Talk 151 | See Code Comments
152 | 153 |If you'd like to learn how to build an entire production app using Meteor and React, i'm finishing a screencast series that feels like a pair programing session. We'll start from scratch and build a production ready MVP of a photo sharing social network site.
158 | 159 |Check it out here: React Meteor Tutorials
160 | 161 |We'll use techniques like TDD unit testing and acceptance testing to build a solid codebase. We'll talk about how to structure your app so it responds to change so it won't become brittle over time... something that other tutorials don't mention.
173 | 174 |We'll even TDD our React views, something that was previously too slow to even consider using traditional view frameworks.
175 | 176 |I've built several production apps that handle thousands of users a day. Learn some tips and tricks on making a production Meteor app that won't tip over with a few hundred concurrent users.
177 | 178 |Meteor can be very magical out of the box. We'll turn off a lot of that and build things manually at first. You can always add in the magic if you'd like. At the end you'll have a solid understanding on how the system is working.
179 | 180 |