Express、VueJS 和 PostgreSQL 入门指南
我们都听说过 MEAN(MongoDB Express Angular NodeJS )技术栈,或者最近出现的MERN(MongoDB Express React NodeJS )技术栈。
虽然市面上有很多使用这些技术栈的入门套件,但我想要的是类似但有一些改动的。我想把 MongoDB 换成 PostgreSQL,因为它功能强大,几乎可以胜任任何任务;我还想把 React 换成 VueJS,因为我发现 Vue 更容易上手,对新手更友好。
我没找到类似的东西,所以就自己做了一个。就叫它 PEVN(PostgreSQL Express View ueJS NodeJS )栈吧,我知道……一点创意都没有!
我花了几个小时才把所有东西都设置成我想要的样子。我把整个过程记录了下来,希望能帮到其他想做同样事情的人,具体内容如下。
TL;DR - https://github.com/jesalg/penv-starter
NodeJS
在开始之前,请确保已安装 NodeJS。我发现最简单的方法是通过 nvm 安装。Rails 开发人员会发现它与 rvm 非常相似。要安装 nvm,请运行以下命令,这些命令将安装 nvm 和最新版本的 NodeJS:
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash
$ source ~/.bash_profile
$ nvm install node
$ nvm use node
表达
安装 Express 最简单的方法是使用生成器:
$ npm install express-generator -g
$ express pevn-starter
$ cd pevn-starter && npm install
VueJS
现在我们已经有了一个基本应用,接下来进入有趣的部分。我们将把每个 Express 视图都当作一个独立的 VueJS 应用(MVVM 模式)来处理,它会从 DOM 中获取所需数据,或者向服务器发送 AJAX 请求。
因此,对于这个例子,假设我们有了 Jade 视图views/index.jade,我们希望将其关联的 VueJS 应用和样式放在 Jade 视图中client/css/index.css,client/js/index.js以便/client/js/Index.vue当渲染 Jade 视图时,它会运行 Index Vue 应用。
所以我们需要告诉视图views/index.jade加载我们打包好的资源文件:
extends layout
block content
#index(data-visitors-json="#{JSON.stringify(visitors)}")
script(src="#{webpack_asset('index', 'js')}")
link(rel='stylesheet', href="#{webpack_asset('index', 'css')}")
我们的client/js/index.js程序将引导我们的 Index Vue 应用:
import Vue from 'vue'
import Index from './Index.vue'
new Vue({
el: '#index',
data: {
visitors: []
},
render (createElement) {
return createElement(Index)
},
beforeMount() {
this.visitors = JSON.parse(this.$el.dataset.visitorsJson) //Grab this data from the DOM
}
})
我们的 Vue 应用位于client/js/Index.vue:
<template>
<div>
<h1>Hello World</h1>
<p>Welcome to PostgreSQL, Express, VueJS, NodeJS starter</p>
<p>Here are the last 10 visitors:</p>
<table>
<thead>
<th>ID</th>
<th>IP</th>
<th>User Agent</th>
</thead>
<tr v-for="(visitor, index) in visitors" :key="index">
<td>{{ visitor.id }}</td>
<td>{{ visitor.ip }}</td>
<td>{{ visitor.user_agent }}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
data() {
return {
visitors: []
}
},
methods: {
},
created() {
this.visitors = this.$parent.visitors; //Grab this data from the parent
}
}
</script>
暂时不用担心显示访客列表的逻辑,我们稍后再谈。
Webpack
为了创建视图的打包 index.js 资源文件,我们需要安装 Webpack、VueJS 及其相关依赖项:
$ npm install webpack extract-text-webpack-plugin assets-webpack-plugin babel-core babel-loader babel-preset-es2015 css-loader file-loader style-loader url-loader vue-template-compiler --save-dev
$ npm install vue express-webpack-assets webpack-dev-middleware webpack-hot-middleware
接下来,我们在项目根目录创建 webpack.config.js 文件,并将以下内容粘贴到其中:
var path = require('path')
var webpack = require('webpack')
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var SaveHashes = require('assets-webpack-plugin');
var isProd = (process.env.NODE_ENV === 'production');
var config = {
entry: {
index: [
path.join(__dirname, 'client/js/index.js'),
path.join(__dirname, 'client/css/index.css')
],
},
output: {
path: path.join(__dirname, 'public/dist/'),
publicPath: '/dist/',
filename: '[name].[hash].js'
},
resolve: {
extensions: ['.js', '.vue'],
alias: {
vue: isProd ? 'vue/dist/vue.min.js' : 'vue/dist/vue.js',
}
},
module: {
rules: [{
test: /\.vue$/,
exclude: /node_modules/,
use: [{
loader: 'vue-loader'
}]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [{
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}]
},
{
test: /\.svg/,
use: {
loader: 'svg-url-loader',
options: {}
}
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: "style-loader",
use: {
loader: 'css-loader',
options: {
minimize: true
}
}
})
},
]
},
devtool: 'eval-source-map',
plugins: [
new SaveHashes({
path: path.join(__dirname, 'config')
}),
new ExtractTextPlugin({
publicPath: '/dist/',
filename: '[name].[hash].css',
allChunks: true
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
]
}
if (isProd) {
config.plugins.push(new webpack.optimize.UglifyJsPlugin());
}
module.exports = config
我们的 Webpack 配置将确保客户端文件夹中的资源被编译成一个压缩的 JS 和 CSS 包,并带有可清除缓存的哈希文件名。
现在我们需要告知 Express 我们正在使用 Webpack,并且希望在启动时运行它。因此,请在 app.js 文件中添加以下代码:
var webpack = require('webpack')
var webpackDevMiddleware = require('webpack-dev-middleware')
var webpackHotMiddleware = require('webpack-hot-middleware')
var webpackAssets = require('express-webpack-assets')
.
.
.
// webpack setup
if (NODE_ENV === 'production') {
app.use(express.static(__dirname + '/dist'));
} else {
const compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
stats: { colors: true }
}))
app.use(webpackHotMiddleware(compiler))
}
app.use(webpackAssets('./config/webpack-assets.json', {
devMode: NODE_ENV !== 'production'
}));
.
.
.
PostgreSQL
最后,我们通过安装sequelize ORM 及其相关依赖项来添加 pg 支持:
$ npm install sequelize pg pg-hstore --save
$ npm install sequelize-cli --save-dev
$ ./node_modules/.bin/sequelize init
运行这些命令会生成一些设置代码,您只需要更新您的config/config.json连接信息即可:
{
"development": {
"username": "root",
"password": null,
"database": "pevn_development",
"host": "127.0.0.1",
"dialect": "postgres"
},
"test": {
"username": "root",
"password": null,
"database": "pevn_test",
"host": "127.0.0.1",
"dialect": "postgres"
},
"production": {
"username": "root",
"password": null,
"database": "pevn_production",
"host": "127.0.0.1",
"dialect": "postgres"
}
}
有了这些信息,我们就可以创建第一个模型并运行迁移了:
$ ./node_modules/.bin/sequelize model:generate --name Visitor --attributes ip:string,user_agent:string
$ ./node_modules/.bin/sequelize db:create
$ ./node_modules/.bin/sequelize db:migrate
在本示例中,我们将创建一个名为 Visitors 的表,该表会在每次用户访问首页时记录用户的 IP 地址和 UserAgent 字符串,并输出最近 10 条记录:
var express = require('express');
var models = require('../models');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
models.Visitor.create({
user_agent: req.get('User-Agent'),
ip: req.ip,
}).then(() => {
models.Visitor.findAll({limit: 10, order: [['createdAt', 'DESC']]}).then((visitors) => {
res.render('index', { title: 'PEVN Stack!', visitors: visitors });
})
});
});
module.exports = router;
结论
至此,我们就完成了整个流程,形成了一个闭环。如果一切顺利,您现在应该能够使用以下命令在 4000 端口运行您的应用程序:
$ npm start
您可能会注意到,每次更改服务器代码时,应用程序都需要重启,这可能会非常烦人。我们可以改用 nodemon,这样应用程序就可以在代码更改时自动重启:
$ npm install --save-dev nodemon
在我们的配置中nodemon.json,我们可以设置当服务器端逻辑发生更改时,程序自动重启:
{
"verbose": true,
"ignore": ["public/"],
"events": {
"restart": "osascript -e 'display notification \"App restarted due to:\n'$FILENAME'\" with title \"nodemon\"'"
},
"watch": ["routes/"],
"env": {
"NODE_ENV": "development"
},
"ext": "js jade"
}
最后,我们可以将 npm start 命令更新为:nodemon app.js
还有一些更有趣的功能,我为了方便快速入门就没一一介绍。例如,我们可以用 Babel 来运行 NodeJS 服务器逻辑,这样服务器端也能使用 ES6 语法了。期待社区提交这类增强功能的 pull request! :)
这篇文章最初发表在我的博客上。如果您喜欢这篇文章,请在社交媒体上分享并关注我的推特!
文章来源:https://dev.to/jesalg/getting-started-with-express-vuejs--postgresql--24db
