Eu, eu mesmo e… um Projeto Base
KoaJS e Aurelia
Esse post vou explicar como criar um esqueleto para um projeto web usando Javascript ES6 como linguagem no NodeJS, ExpressJS como framework para API e Aurelia como framework frontend.
ExpressJS
A criação do esqueleto tem como base o gerado com o comando “express”, mas como quero utilizar os recursos das versões mais novas do Javascript, temos que dar uma alterada.
A estrutura de diretórios fica da seguinte maneira:
.
├── lib
│ ├── app.js
│ └── routes
├── package.json
├── public
└── src
├── app.js
└── routes
- src/ contém arquivos não transpilados
- lib/ contém os arquivos transpilados
- src/app.js contém o servidor em questão com as configurações do ExpressJS
- api/index.js contém as configurações para as rotas abaixo do /api
- api/resources/*.js as rotas para os recursos
- public contém os arquivos estáticos, no caso o Aurelia
O app.js ficará da seguinte forma
import fs from 'fs';
import path from 'path';
import http from 'http';
import favicon from 'serve-favicon';
import logger from 'morgan';
import cookieParser from 'cookie-parser';
import bodyParser from 'body-parser';
import express, {Router} from 'express';import api from './api';const PORT = process.env.PORT || '3000';
const app = express();app.set('port', PORT);app.use(favicon(path.join(__dirname, '..', 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, '..', 'public')));app.use('/api', api);app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
next();
});
}app.use(function(err, req, res, next) {
res.status(err.status || 500);
next();
});var server = http.createServer(app);server.listen(PORT);
O api/index.js:
import {Router} from 'express';
import Users from './resources/users';const router = new Router();const config = {
'/users' : Users
}for(var path in config){
router.use(path, config[path]);
}export default router;
Ali você pode ver um mapeamento para o reecurso Users para a path /users.
O recurso Users no arquivo api/resources/users.js pode ser configurado da seguinte maneira:
import {Router} from 'express';
const router = new Router();
router.post('/', (req, res, next) => {
res.json({cod : 200, msg : 'OK'});
next();
});
router.get('/', (req, res, next) => {
res.json([]);
next();
});
router.put('/:id', (req, res, next) => {
res.json({cod : 200, msg : 'OK'});
next();
});
router.delete('/:id', (req, res, next) => {
res.json({cod : 200, msg : 'OK'});
next();
});
export default router;
Assim, para “compilar” os arquivos de src/ para lib/ configuramos o package.json com as seguintes dependências:
{
...
"scripts": {
"autobuild": "./node_modules/.bin/babel -w -d lib src/",
"autorun": "./node_modules/.bin/nodemon lib/app.js"
},
"dependencies": {
"body-parser": "1.15.2",
"cookie-parser": "1.4.3",
"express": "4.14.0",
"morgan": "1.7.0",
"serve-favicon": "2.3.0"
},
"devDependencies": {
"babel-cli": "6.14.0",
"babel-preset-es2015": "6.14.0",
"babel-preset-es2016": "6.11.3",
"nodemon": "1.10.2"
},
"babel": {
"presets": [
"es2015"
]
},
...
}
Note a configuração do BabelJS para usar o ES2015.
Note também os scripts do NPM. POdemos então rodar o seguinte comando para buildar e rodar:
$ npm run autobuild
$ npm run autorun
Pronto, teremos um servidor ExpressJS rodando em http://localhost:3000
Aurelia
Para o Aurelia, fazemos download do própio site http://aurelia.io/downloads/basic-aurelia-project.zip
E descompactamos para a pasta public.
Como não quero usar Typescript, mudamos a linha contendo:
<script src=”scripts/config-typescript.js”></script>
Para:
<script src="scripts/config-esnext.js"></script>
Como quero usar o Routing do Aurelia, devemos adicionar o script:
<script src="scripts/aurelia-routing.min.js"></script>
E a configuração para o JSPM
<script src="config.js"></script>
O public/index.html ficará assim:
<!DOCTYPE html>
<html>
<head>
<title>Aurelia</title> </head>
<body aurelia-app="src/main">
<script src="scripts/system.js"></script>
<script src="config.js"></script>
<script src="scripts/config-esnext.js"></script>
<script src="scripts/aurelia-core.min.js"></script>
<script src="scripts/aurelia-routing.min.js"></script>
<script>
System.import('aurelia-bootstrapper');
</script>
</body>
</html>
Como quero usar Bootstrap e o FontAwesome, vamos então instalar essas dependências e outras dentro da pasta public:
$ jspm install aurelia-fetch-client bootstrap font-awesome css
Próximo passo é criar os arquivos main.js, app.js e app.html dentro da pasta public/src.
main.js
import 'aurelia-fetch-client';export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging();
aurelia.start().then(() => aurelia.setRoot());
}
app.js
import 'bootstrap/css/bootstrap.min.css!';
import 'font-awesome';export class App {
configureRouter(config, router) {
this.router = router;
config.title = '7dbs7ws';
config.map([
{ route: '', title: 'Home', name: 'home', moduleId: './home/index' , nav: true}
]);
}
}
app.html
<template>
<div class="col-lg-3">
<ul class="nav nav-sidebar">
<li repeat.for = "row of router.navigation">
<a href.bind = "row.href">${row.title}</a>
</li>
</ul>
</div>
<div class="col-lg-9">
<router-view></router-view>
</div>
</tempalte>
Agora criamos um módulo simples:
Dentro da pasta public/src/home:
index.html
<template>
<div class="jumbotron">
<h1>${heading}</h1>
</div>
</template>
index.js
export class Home {
constructor(){
this.heading = 'Teste';
}
}
Finalmente
Pronto, acho que agora ao acessar http://localhost:3000 você um app base para os projetos.
GitHub
Você pode fazer clone de um aqui também:
EDIT 2016–09–27
Adicionei o AdminLTE, uma variação do Bootstrap com Dashboards.
Assim, foram modificados as dependências:
jspm install -y github:almasaeed2010/AdminLTE
O main.js precisa carregá-lo:
import 'aurelia-fetch-client';
import 'jquery-ui';
import AdminLTE from 'almasaeed2010/AdminLTE';export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging();
aurelia.start()
.then(() => aurelia.setRoot())
.then(() => $.AdminLTE.layout.activate()); // Este é necessário para o layout ficar correto.
}
E o app.html precisa carregar as dependências:
<require from="../jspm_packages/github/almasaeed2010/AdminLTE@2.3.6/bootstrap/css/bootstrap.min.css"></require><require from="../jspm_packages/github/almasaeed2010/AdminLTE@2.3.6/dist/css/AdminLTE.min.css"></require><require from="../jspm_packages/github/almasaeed2010/AdminLTE@2.3.6/dist/css/skins/skin-blue.min.css"></require>
E o index.html tem as classes necessárias para carregar a skin:
<body aurelia-app="src/main" class="hold-transition skin-blue sidebar-mini">
Fora isso, o app.html ainda tem as tags e classes necessárias para deixá-lo na estrutura de dashboard.
Modificações
Deixei de usar o mais famoso ExpressJS e inclui o KoaJS. Do mesmo criador, Koa usa novos recursos do Javascript, como async/await.