多人博客網站初版上線啦,歡迎圍觀,吐槽

網站地址javascript

代碼開源地址css

時間大概是在兩年前吧,那時候剛接觸到 nodejs,立志成爲一名優秀全棧攻城獅的我,心心念着得有一個屬於本身的網站。因而說幹就幹,一邊學着一邊搗鼓的各類花樣。html

曾夢想仗劍走天涯,然然後面由於工做忙就沒去成,個人這個網站也由於各類緣由遲遲沒能上線,這其中也作過了好幾個版本,一開始是先後端分離的,前端使用 angularjs(後面又改爲了 vue),後端是 nodejs + mongodb,等這一版的也差很少作好的時候,感受不是本身想要的樣子,因此也就沒上線。到後面以爲 golang 好玩,又去用它寫了一些後端的接口。前端

到了今年三月份的時候,終於發現網站這個目標確實是拖了很長時間了。抽時間好好想了下本身想要作什麼,決定拋棄以前的那套代碼,不用本身比較熟悉的 先後端分離,vue 等技術,而使用 ejs 模板渲染,nodejs 的 Sequelize orm 庫,使用 session 而不是 jwt 來持久化用戶登陸等。vue

代碼基本上是晚上抽時間寫的,後面由於加班,也停了一段時間。中途若是遇到一些問題,有時候進度也會耽擱個幾天。再加上一些設計以及前端展現上的修修補補,致使整個項目也是花了比較長的時間。好在是一個蘿蔔一個坑的慢慢踩了過來,如今以爲網站終於能夠上線了,後面要作的工做就是完善網站的一些沒有功能(包括後端的管理界面等),修改一些的實現方式(準確的說就是優化代碼),以及更重要的是豐富網站內容,也就是寫博客記錄一些成長路上的風景吧。java

到此爲止,廢話也很少說了,代碼也開源到了GitHub上,有興趣的朋友能夠去圍觀一下,歡迎 start,也歡迎在 issue 裏提出,指正各類問題。node

說一下項目的運行方式吧,首先要 nodejs 環境,須要全局安裝 gulp、nodemon 等包,而後數據存儲使用的 mysql + redis。等環境準備好了以後,就須要添加一些配置文件,好比在 config/env/ 下建立 development.js 文件,裏面須要提供發郵箱的郵件地址,以及 github 第三方登陸的 clientID 等。mysql

module.exports = {
	email: {
		account: '',
		pwd: ''
	},
    github: {
        clientID: '',
        clientSecret: '',
        callbackUrl: ``
    }
};

接下來就是安裝開發運行所須要的各類依賴包吧,跑一下 yarn install 就好了,這個過程可能須要花個幾分鐘時間。
等到全部的包都安裝完畢後,直接跑 npm start 命令,看到 終端上顯示 全部的 gulp 任務 finished,Server is running at port 3000 的時候,就能夠打開瀏覽器訪問 localhost:3000 了。
接下來貼上一些項目裏面的代碼吧,若是上不了首頁就悲劇了。

 1 require('dotenv').config()
 2 
 3 const express = require('express')
 4 const passport = require('passport')
 5 const models = require('./config/db/model')
 6 const port = process.env.PORT
 7 
 8 const app = express()
 9 
10 require('./config/passport')(passport)
11 require('./config/express')(app, passport)
12 require('./config/routes')(app, passport)
13 
14 models
15     .sequelize
16     .sync()
17     .then(() => {
18         app.listen(port, () => {
19             console.log(`Server is running at port ${port}`)
20         })
21     })
22 
23 module.exports = app

 



Gulp 的打包配置nginx

  1 // vinyl 是一個簡單的描述文件的元數據對象
  2 // https://github.com/gulpjs/vinyl
  3 const path = require('path')
  4 const gulp = require('gulp')
  5 const del = require('del')
  6 const glob = require('glob')
  7 const babelify = require('babelify')
  8 const runSequence = require('run-sequence')
  9 const plumber = require('gulp-plumber')
 10 const notify = require('gulp-notify')
 11 const gulpif = require('gulp-if')
 12 const sass = require('gulp-sass')
 13 const debug = require('gulp-debug')
 14 const cached = require('gulp-cached')
 15 const remember = require('gulp-remember')
 16 const autoprefixer = require('gulp-autoprefixer')
 17 const sourcemaps = require('gulp-sourcemaps');
 18 const size = require('gulp-size');
 19 const cssnano = require('gulp-cssnano')
 20 const uglify = require('gulp-uglify')
 21 const rename = require('gulp-rename')
 22 const htmlmin = require('gulp-htmlmin')
 23 const imagemin = require('gulp-imagemin')
 24 const browserify = require('browserify')
 25 const source = require('vinyl-source-stream');
 26 const buffer = require('vinyl-buffer');
 27 const rev = require('gulp-rev');
 28 const watchify = require('watchify')
 29 const lazypipe = require('lazypipe')
 30 const revCollector = require('gulp-rev-collector');
 31 const es = require('event-stream')
 32 const argv = require('yargs').argv
 33 
 34 // 將打包後的靜態資源 放到nginx服務器上
 35 const bundleAssetsDir = argv.build_mode === 'deploy' && argv.assets_path ? argv.assets_path : './public/static/'
 36 const jsAssetsDir = path.join(bundleAssetsDir, 'js')
 37 const cssAssetsDir = path.join(bundleAssetsDir, 'css')
 38 const imgAssetsDir = path.join(bundleAssetsDir, 'image')
 39 const revAssetsDir = path.join(bundleAssetsDir, 'rev')
 40 const htmlAssetsDir = path.join('./app/view')
 41 
 42 const AUTOPREFIXER_BROWSERS = [
 43     'ie >= 10',
 44     'ff >= 30',
 45     'chrome >= 34',
 46     'safari >= 7',
 47     'opera >= 23'
 48 ];
 49 
 50 const jsChannel = lazypipe()
 51     .pipe(uglify)
 52     .pipe(gulp.dest, jsAssetsDir)
 53 
 54 let watch = false
 55 
 56 function getEntryFiles (path, option) {
 57     return glob.sync(path, option)
 58 }
 59 
 60 /**
 61  * 打包js任務
 62  * @param {Object} bundle 各入口文件的browserify對象
 63  * @param {string} filename 入口文件名
 64  * @return {stream} stream 對象
 65  */
 66 function jsTask ({ bundle, filename }) {
 67     return bundle
 68     .bundle()
 69     .pipe(plumber({
 70         errorHandler: notify.onError('Error: <%= error.message %>')
 71     }))
 72     .pipe(source(filename))
 73     // 代替 gulp-streamify,來轉換 vinyl 流
 74     .pipe(buffer())
 75     .pipe(rename({ dirname: '' }))
 76     .pipe(sourcemaps.init())
 77     .pipe(debug({ title: 'script' }))
 78     .pipe(size({ title: 'script' }))
 79     .pipe(sourcemaps.write(''))
 80     .pipe(gulp.dest(jsAssetsDir))
 81 }
 82 
 83 /**
 84  * 若是一個文件被刪除了,則將其忘記
 85  * @param {*} event
 86  */
 87 function watchDel (event) {
 88     if (event.type === 'deleted') {
 89         // gulp-cached 的刪除 api
 90         delete cached.caches.scripts[event.path]
 91         // gulp-remember 的刪除 api
 92         remember.forget('scripts', event.path)
 93     }
 94 }
 95 
 96 gulp.task('style', () => {
 97     return gulp.src('./src/scss/*.scss')
 98         .pipe(plumber({
 99             errorHandler: notify.onError('Error: <%= error.message %>')
100         }))
101         // .pipe(cached('style-task'))
102         .pipe(sourcemaps.init())
103         .pipe(sass())
104         .pipe(cssnano({
105             // 不修改 z-index
106             safe: true
107         }))
108         .pipe(autoprefixer(AUTOPREFIXER_BROWSERS))
109         .pipe(debug({ title: 'style' }))
110         // .pipe(remember('style-task'))
111         .pipe(size({ title: 'style' }))
112         .pipe(sourcemaps.write(''))
113         .pipe(gulp.dest(cssAssetsDir))
114 })
115 
116 gulp.task('script', () => {
117     let entryJs = getEntryFiles('./src/js/*.js')
118     let bundleTasks = entryJs.map(filename => {
119         const bundle = browserify({
120             entries: [filename],
121             cache: {},
122             packageCache: {},
123             plugin: [watch ? watchify : null],
124             transform: babelify
125         })
126         if (watch) {
127             bundle.on('update', function () {
128                 jsTask.call(null, { bundle, filename })
129             })
130         }
131         return { bundle, filename }
132     })
133     return es.merge(bundleTasks.map(jsTask));
134 })
135 
136 gulp.task('image', () => {
137     return gulp.src(['./src/image/*', './src/image/**/*'])
138         .pipe(cached('image-task'))
139         .pipe(imagemin([
140             imagemin.gifsicle({ interlaced: true }),
141             imagemin.jpegtran({ progressive: true }),
142             imagemin.optipng({ optimizationLevel: 5 }),
143             imagemin.svgo({
144                 plugins: [
145                     { removeViewBox: true },
146                     { cleanupIDs: false }
147                 ]
148             })
149         ]))
150         .pipe(debug({ title: 'image' }))
151         .pipe(remember('image-task'))
152         .pipe(size({ title: 'image' }))
153         .pipe(gulp.dest(imgAssetsDir))
154 })
155 
156 gulp.task('html', () => {
157     return gulp.src('./src/page/**/*.html')
158         .pipe(cached('html-task'))
159         .pipe(debug({ title: 'html' }))
160         .pipe(remember('html-task'))
161         .pipe(gulp.dest(htmlAssetsDir))
162 
163 })
164 
165 gulp.task('rev', () => {
166     return gulp.src([path.join(jsAssetsDir, '*.js'), path.join(cssAssetsDir, '*.css')])
167         .pipe(rev())
168         .pipe(gulpif('*.js', jsChannel()))
169         .pipe(gulpif('*.css', gulp.dest(cssAssetsDir)))
170         .pipe(rev.manifest({
171             merge: true
172         }))
173         .pipe(gulp.dest(revAssetsDir))
174 })
175 
176 gulp.task('rev-collector', () => {
177     return gulp.src([path.join(revAssetsDir, '*.json'), path.join(htmlAssetsDir, '*.html')])
178         .pipe(revCollector({
179             replaceReved: true
180         }))
181         .pipe(htmlmin({
182             removeComments: true,
183             collapseWhitespace: true,
184             collapseBooleanAttributes: true,
185             removeAttributeQuotes: true,
186             removeRedundantAttributes: true,
187             removeEmptyAttributes: true,
188             removeScriptTypeAttributes: true,
189             removeStyleLinkTypeAttributes: true,
190             removeOptionalTags: true
191         }))
192         .pipe(size({ title: 'html' }))
193         .pipe(gulp.dest(htmlAssetsDir))
194 })
195 
196 gulp.task('clean', () => del([bundleAssetsDir, htmlAssetsDir], { force: true }))
197 
198 gulp.task('style:watch', () => {
199     const watcher = gulp.watch(['./src/scss/**/*.scss'], ['style'])
200     watcher.on('change', watchDel)
201 })
202 
203 gulp.task('image:watch', () => {
204     const watcher = gulp.watch(['./src/image/**/*'], ['image'])
205     watcher.on('change', watchDel)
206 }
207 )
208 gulp.task('html:watch', () => {
209     const watcher = gulp.watch(['./src/page/**/*.html'], ['html'])
210     watcher.on('change', watchDel)
211 })
212 
213 gulp.task('watch', () => {
214     watch = true
215     runSequence(
216         'clean',
217         ['script', 'style', 'html', 'image'],
218         ['style:watch', 'html:watch', 'image:watch']
219     )
220 })
221 
222 gulp.task('build', cb => {
223     watch = false
224     return runSequence(
225         'clean',
226         ['script', 'style', 'html', 'image'],
227         'rev',
228         'rev-collector',
229         cb
230     )
231 })
232 
233 gulp.task('default', ['build'])

最後再一次貼上網站以及開源地址,歡迎各路大佬圍觀,吐槽,指正。git

網站地址

代碼開源地址

相關文章
相關標籤/搜索