最近在使用 ThinkJS + Vue2.0 寫一個簡單的項目,該項目分為用户端和管理界面,分別對應 vue 的兩個頁面index
和admin
,用户端、管理界面自身是基於 vue 構建的單頁應用,服務端採用 thinkjs 的提供 api。
項目目錄結構如下:
.
├── README.md
├── client
│ ├── README.md
│ ├── build
│ ├── config
│ ├── package.json
│ ├── src
│ │ ├── components
│ │ ├── modules
│ │ └── pages
│ │ ├── admin
│ │ └── index
│ └── static
└── server
├── src
│ ├── bootstrap
│ ├── config
│ ├── controller
│ │ ├── admin
│ │ ├── base.js
│ │ ├── home
│ │ └── index.js
│ ├── logic
│ └── model
├── view
│ ├── admin.html
│ └── index.html
└── www
└── static
複製代碼
client 的配置
直接使用 vue 官方的 vue-cli 創建項目,選擇使用 webpack 構建。
修改config/index.js
,給 webpack-dev-server 添加 proxyTable:
proxyTable: {
'/api' : {
target: 'http://localhost:8360/api/',
changeOrigin: true,
pathRewrite: {
'^/api': '/'
}
}
},
複製代碼
然後參照《使用 Vue-cli 搭建多頁面應用時對項目結構和配置的調整》的方法將其改為多頁應用,具體方法為:
調整項目目錄,創建src/pages/index
,將src/assets
、src/router
、src/App.vue
、src/main.js
和./index.html
移動到該目錄中,並將main.js
改名為index.js
。
修改構建腳本build/utils.js
,添加:
var glob = require('glob')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var PAGE_PATH = path.resolve(__dirname, '../src/pages')
var merge = require('webpack-merge')
exports.entries = function() {
var entryFiles = glob.sync(PAGE_PATH + '/*/*.js')
var map = {}
entryFiles.forEach((filePath) => {
var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
map[filename] = filePath
})
return map
}
exports.htmlPlugin = function() {
let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
return entryHtml.map((filePath) => {
let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
let conf = {
template: filePath,
filename: filename + '.html',
chunks: ['manifest', 'vendor', filename],
inject: true
}
if (process.env.NODE_ENV === 'production') {
conf = merge(conf, {
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
})
}
return new HtmlWebpackPlugin(conf)
})
}
複製代碼
修改build/webpack.base.conf.js
的入口配置:
module.exports = {
context: path.resolve(__dirname, '../'),
entry: utils.entries(),
...
...
}
複製代碼
修改build/webpack.dev.conf.js
和build/webpack.prod.conf.js
的插件配置:
plugins: [
...
...utils.htmlPlugin(),
...
]
複製代碼
創建 src/pages/admin
目錄,添加admin.html
文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta >
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>Admin</h1>
</body>
</html>
複製代碼
創建 src/pages/404
目錄,添加404.html
文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta >
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>404</title>
</head>
<body>
<h1>404 Not Found</h1>
</body>
</html>
複製代碼
修改 webpack-dev-server 的路由表:
historyApiFallback: {
rewrites: [
{ from: /^\/$/, to: '/index.html' },
{ from: /^\/admin\/?$/, to: '/admin.html' },
{ from: /./, to: '/404.html' }
],
},
複製代碼
至此 client 端的配置就完成了,可以通過 npm start
啟動 client 端,通過 http://localhost:8080
訪問頁面。
server 的配置
直接使用 ThinkJS 官方的 think-cli 創建項目,修改src/config/router.js
,添加路由:
module.exports = [
[/^\/api\/(.*)/i, '/:1'],
[/^\/$/i, '/'],
[/^\/admin\/?$/i, '/index/admin'],
[/\//, 'index/_404', 'get']
];
複製代碼
修改src/controller/index.js
渲染模板:
const Base = require('./base.js');
module.exports = class extends Base {
indexAction() {
return this.display('index.html');
}
adminAction() {
return this.display('admin.html');
}
_404Action() {
return this.display('404.html');
}
};
複製代碼
至此服務器的配置完成,啟動 server 端,client 可通過 http://localhost:8080/api
訪問 API。
開發服務端 API
在 server 中任意 controller 暴露的 API 可以通過 /api/controller/action
來訪問,比如:
const Base = require('./base.js');
module.exports = class extends Base {
indexAction() {
return this.success('test');
}
};
複製代碼
可以通過 http://localhost:8080/api/test
訪問:
{
errno: 0,
errmsg: "",
data: "test"
}
複製代碼
添加新頁面 abc
在 client 的 src/pages
目錄下創建新的頁面 src/pages/abc/abc.html
,同時修改 webpack.dev.config.js
,historyApiFallback 中添加新的頁面路由。
historyApiFallback: {
rewrites: [
{ from: /^\/$/, to: '/index.html' },
{ from: /^\/admin\/?$/, to: '/admin.html' },
{ from: /^\/abc\/?$/, to: '/abc.html' },
{ from: /./, to: '/404.html' }
],
},
複製代碼
在 server 的 src/controller/index.js
中創建新的 action
const Base = require('./base.js');
module.exports = class extends Base {
...
abcAction() {
return this.display('abc.html');
}
_404Action() {
return this.display('404.html');
}
};
複製代碼
修改 router.js 添加新路由:
module.exports = [
[/^\/api\/(.*)/i, '/:1'],
[/^\/$/i, '/'],
[/^\/admin\/?$/i, '/index/admin'],
[/^\/abc\/?$/i, '/index/abc'],
[/\//, 'index/_404', 'get']
];
複製代碼
分別重啟 sever、client 即可。
生產環境構建
生產環境構建非常簡單,直接在 client 下運行npm run build
,將dist
下生成的文件*.html
拷貝到 server 的view
目錄下,將dist/static
目錄拷貝到 server 的www
目錄下,然後將 server 部署到生產環境運行即可。