sahat / megaboilerplate
- четверг, 9 июня 2016 г. в 03:13:03
CSS
Handcrafted starter projects, optimized for simplicity and ease of use.
Live Demo: http://megaboilerplate.com
Mega Boilerplate is a starter project generator that focuses on simplicity and ease of use, while providing you with flexibility of choices. It was heavily inspired by the Hackathon Starter, but unlike it, you can customize any part of your application stack — from web framework and database to CSS preprocessor and client-side JavaScript framework. Currently, generators are primarily limited to Node.js web apps, but I am planning to expand support for other platforms and languages in the near future.
xcode-select --install
sudo apt-get install build-essential
sudo dnf groupinstall "Development Tools"
sudo zypper install --type pattern devel_basis
Download and extract the project. Then in your Terminal type the following:
$ cd megaboilerplate-app
# Install NPM dependencies
$ npm install
# Start the app
$ node server.js
# Express server listening on port 3000
Note: If you have selected Gulp or NPM build tool, you may also need to run npm run build
command.
Note: If you have selected a database, please make sure it is up and running. For additional information, see Database Setup.
$ cd megaboilerplate-app
# Start Jekyll app
$ jekyll serve
# Server address: http://127.0.0.1:4000/
# Server running... press ctrl-c to stop.
$ cd megaboilerplate-app
# Install Ruby dependencies
$ bundle install
# Start Middleman app
$ bundle exec middleman
# The Middleman is loading
# View your site at "http://localhost:4567"
This JavaScript library boilerplate was inspired and based on Dan Abramov's library-boilerplate project. The main idea here is you write your code in ES6, which then gets transpiled into CommonJS and UMD builds. Consider lodash as an example - a very popular JavaScript library that supports ES6 import
, CommonJS require()
and can be used inside a browser via <script>
tag.
$ cd megaboilerplate-app
# Install NPM dependencies
$ npm install
# ES5 / CommonJS build
$ npm run build
# UMD build
$ npm run build:umd
# Run tests
$ npm test
Install Homebrew package manager. Then follow the steps below to install and setup MongoDB.
# Update Homebrew's package database
$ brew update
# Install MongoDB
$ brew install mongodb
# Create the data directory
$ sudo mkdir -p /data/db
# Set permissions for the data directory
$ sudo chown -R `whoami` /data/db
# Run MongoDB Server
$ mongod
mongod.exe
in C:\Program Files\MongoDB\Server\3.2\bin.# Import the public key used by the package management system
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
# Create a source list file for MongoDB
$ echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list
# Update the repository
$ sudo apt-get update
# Install the latest stable version of MongoDB
$ sudo apt-get install -y mongodb-org
# Start MongoDB service
$ sudo service mongod start
Use database settings below in the .env
file.
Key | Value |
---|---|
DB_HOST |
localhost |
DB_USER |
root |
DB_PASSWORD |
(use root password configured during installation or leave blank) |
DB_NAME |
mysql |
Install Homebrew package manager. Then follow the steps below to install and start MySQL.
# Update Homebrew's package database
$ brew update
# Install MySQL
$ brew install mysql
# Start MySQL Server
$ mysql.server start
Note: Alternatively, you may use XAMPP, which already comes bundled with MySQL and phpMyAdmin.
# Update the repository
$ sudo apt-get update
$ sudo apt-get upgrade
# Install MySQL
$ sudo apt-get install mysql-server
Use database settings below in the .env
file.
Key | Value |
---|---|
DB_HOST |
localhost |
DB_USER |
postgres |
DB_PASSWORD |
(use root password configured during installation) |
DB_NAME |
postgres |
Install Homebrew package manager. Then follow the steps below to install and start PostgreSQL.
# Update Homebrew's package database
$ brew update
# Install PostgreSQL
$ brew install postgres
# Start PostgreSQL Server
$ postgres -D /usr/local/var/postgres
# Update the repository
$ sudo apt-get update
$ sudo apt-get upgrade
# Install PostgreSQL
$ sudo apt-get install postgresql postgresql-contrib
No additional steps required. Package sqlite3
will be automatically installed during npm install
in Getting Started.
Due to the nature of this project, there are too many possible project structure variations to list here. For the sake of simplicity, let's consider just the following project types:
This is perhaps the most straightforward web app type that does not use any client-side JavaScript frameworks or build tools. Is also the closest thing to Hackathon Starter project.
.
├── config/ # Configuration files for OAuth, database, etc.
│ ├── passport.js/ # Passport strategies
├── controllers/ # Express route handlers
├── models/ # Express database models
├── public/
│ ├── css/ # Sass/LESS/PostCSS/CSS stylesheets (both source and generated)
│ ├── fonts/ # Web fonts
│ ├── js/ # Client-side JavaScript and third-party vendor files
├── views/ # Templates
├── test/ # Unit tests
├── .env # API keys, passwords, and other sensitive information
├── server.js # Express application
└── package.json # NPM Dependencies and scripts
The new hotness of the web — Universal JavaScript app, powered by React, Redux, React Router and Server Rendering.
Note: Some files were ommited like gulpfile.js
and webpack.config.js
.
.
├── app/ # React application
│ ├── actions/ # Redux actions
│ ├── components/ # React components
│ ├── reducers/ # Redux reducers
│ ├── store/ # Store initialization and configuration
│ ├── main.js # Client-side app entry-point
│ ├── routes.js # Universal application routes (React Router)
├── controllers/ # Express route handlers
├── models/ # Express database models
├── public/
│ ├── css/ # Sass/LESS/PostCSS/CSS stylesheets (both source and generated)
│ ├── fonts/ # Font Awesome web fonts
│ ├── js/ # Third-party vendor files and generated React app (bundle.js)
├── views/
│ ├── layout.jade # Main container, into which React app is rendered
│ ├── loading.jade # Loading spinner animation for OAuth 1.0 / 2.0 authentication flow inside a popup
├── .babelrc # Babel config
├── .env # API keys, passwords, and other sensitive information
├── server.js # Express application
└── package.json # NPM Dependencies and scripts
Your typical MEAN stack (MongoDB, Express, AngularJS, Node.js). Originally, I was not planning on adding AngularJS 1.x generator, especailly with Angular 2 around the corner. So without investing too much time, I kept it real simple: no Browserify, no ES6 classes, no AngularJS 1.5 components. Once officially released, Angular 2 generator will be more elaborate with quite a few additional options.
.
├── app/ # Angular app directory
│ ├── controllers/ # Angular controllers
│ ├── partials/ # Angular view templates
│ ├── services/ # Angular services
│ ├── store/ # Store initialization and configuration
│ ├── app.js # Main Angular app file
│ ├── index.html # Main layout template
├── controllers/ # Express route handlers
├── models/ # Express database models
├── public/
│ ├── css/ # Sass/LESS/PostCSS/CSS stylesheets (both source and generated)
│ ├── js/ # Compiled Angular app and third-party vendor files, e.g. angular.js, angular-route.js
├── .env # API keys, passwords, and other sensitive information
├── gulpfile.js # Compiles Angular application and templates
├── server.js # Express application
└── package.json # NPM Dependencies and scripts
To use any of the included OAuth providers (e.g. Facebook, Twitter, Google), you will need to obtain API keys. I have included "throw-away" API keys for all OAuth providers to get you up and running quickly, but be sure to update them with your own keys.
.env
file:
FACEBOOK_ID='YOUR_APP_ID'
FACEBOOK_SECRET='YOUR_APP_SECRET'
http://localhost:3000/auth/callback
in the Site URL.Web application
http://localhost:3000
http://localhost:3000/auth/google/callback
.env
file:
GOOGLE_ID='YOUR_CLIENT_ID'
GOOGLE_SECRET='YOUR_CLIENT_SECRET'
http://127.0.0.1:3000/auth/twitter/callback
.env
file:
TWITTER_ID='YOUR_CONSUMER_KEY'
TWITTER_SECRET='YOUR_CONSUMER_SECRET'
Application on and visible to all
http://localhost:3000
http://localhost:3000/auth/vkontakte/callback
.env
file:
VK_ID='YOUR_APPLICATION_ID'
VK_SECRET='YOUR_SECURE_KEY'
Declares a read-only named constant.
const name = 'yourName';
Declares a block scope local variable.
let index = 0;
Using the `${}` syntax, strings can embed expressions.
const name = 'Oggy';
const age = 3;
console.log(`My cat is named ${name} and is ${age} years old.`);
To import functions, objects or primitives exported from an external module. These are the most common types of importing.
import name from 'module-name';
import * as name from 'module-name';
import { foo, bar } from 'module-name';
To export functions, objects or primitives from a given file or module.
export { myFunction };
export const name = 'yourName';
export default myFunctionOrClass
The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected.
myFunction(...iterableObject);
<ChildComponent {...this.props} />
A Promise is used in asynchronous computations to represent an operation that hasn't completed yet, but is expected in the future.
var p = new Promise(function(resolve, reject) { });
The catch()
method returns a Promise and deals with rejected cases only.
p.catch(function(reason) { /* handle rejection */ });
The then()
method returns a Promise. It takes 2 arguments: callback for the success & failure cases.
p.then(function(value) { /* handle fulfillment */, function(reason) { /* handle rejection */ });
The Promise.all(iterable)
method returns a promise that resolves when all of the promises in the iterable argument have resolved, or rejects with the reason of the first passed promise that rejects.
Promise.all([p1, p2, p3]).then(function(values) { console.log(values) });
Arrow function expression. Shorter syntax & lexically binds the this
value. Arrow functions are anonymous.
singleParam => { statements }
() => { statements }
(param1, param2) => expression
const arr = [1, 2, 3, 4, 5];
const squares = arr.map(x => x * x);
The class declaration creates a new class using prototype-based inheritance.
class Person {
constructor(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
incrementAge() {
this.age++;
}
}
Math.floor(Date.now() / 1000);
var now = new Date();
now.setMinutes(now.getMinutes() + 30);
// DD-MM-YYYY
var now = new Date();
var DD = now.getDate();
var MM = now.getMonth() + 1;
var YYYY = now.getFullYear();
if (DD < 10) {
DD = '0' + DD;
}
if (MM < 10) {
MM = '0' + MM;
}
console.log(MM + '-' + DD + '-' + YYYY); // 03-30-2016
// hh:mm (12 hour time with am/pm)
var now = new Date();
var hours = now.getHours();
var minutes = now.getMinutes();
var amPm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12;
minutes = minutes < 10 ? '0' + minutes : minutes;
console.log(hours + ':' + minutes + ' ' + amPm); // 1:43 am
var today = new Date();
var nextWeek = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000);
var today = new Date();
var yesterday = date.setDate(date.getDate() - 1);
Once you are ready to deploy your app, you will need to create an account with a cloud platform to host it. These are not the only choices you have, but they are my top picks.
heroku login
, then enter your Heroku credentialsgit init
git add .
git commit -m 'Initial commit'
Then run heroku create
to create a new Heroku app and link it with your current Git repository
Creating app... done, ⬢ floating-mesa-51019
https://floating-mesa-51019.herokuapp.com/ | https://git.heroku.com/floating-mesa-51019.git
Run git push heroku master
and you are done!
Note: If you have created a new app via Heroku Dashboard, you can link it with an existing Git repository by running:
heroku git:remote -a your-heroku-app-name
For more information, please visit Getting Started on Heroku with Node.js.
TODO: Deployment instructions for SQL and MongoDB databases. (Heroku PostgresL, Compose, MongoLab)
https://username@appname.scm.azurewebsites.net:443/appname.git
git init
git add .
git commit -m 'Initial commit'
git remote add azure https://username@appname.scm.azurewebsites.net:443/appname.git
git push azure master
, and when prompted, enter your password created under Deployment credentialsTODO
Despite being such a small library, Redux can be difficult to grasp for beginners. It took me almost three days until Redux "clicked" for me, even with my prior experience of working with React and Flux. Here is a TL;DR: summary:
Concept | Description |
---|---|
Actions | Your application events, e.g. fetch data from server. Success and failure events of data fetching could also be actions. Actions are just plain JavaScript objects. They typically have some data associated with it. For example, LOGIN_ERROR action may contain an error message. Actions describe the fact that something happened, but don't specify how the application’s state changes in response. This is the job of a reducer. |
Reducers | Basically your action handlers, internally implemented via Array.prototype.reduce() . This is where you specify how should the application state be updated when LOGIN_ERROR action is dispatched, for example. And that's it. How that state affects your application should still be managed in your components. One thing to note, you never mutate the state, but rather create a new copy of your current state + new changes using Object.assign() . |
Store | Brings actions and reducers together. Store holds entire application state, allows you access current state via getState() , and update application state via dispatch(action) . You typically have just one Redux store that is configured during the inital bootstrap stage. |
Provider | Syntactic sugar from react-redux library. <Provider> component wrapper makes the Redux store available to the connect() function. Alternatively, you can manually pass store as a prop to every connect() ed component. connect() is another syntactic sugar provided by react-redux which connects a React component to a Redux store. Alternatively, you can manually subscribe/unsubscribe to/from a store during componentDidMount() and componentDidUnmount() lifecycle of each component. |
Container | So-called smart components that are aware of Redux, whereas traditional components are now considered dumb components, which are not aware of Redux; they just render markup with given props. I intentionally combined containers and components into simply — components for the sake of simplicity. |
If you have built an app using Mega Boilerplate, please enter yourself here by sending a pull request.
Pull requests from beginners and seasoned JavaScript developers are welcome! As it stands, Mega Boilerplate is pretty large in scope to be maintained by a single person, so I am asking for your help to contribute where you can, whether it's a small fix in README or adding a whole new generator type, e.g. Meteor, Angular 2, React Native, Electron.
MIT