【第二章】BCMS应用的express架构解析1
既然选择了express+webpack的架构,那就需要明确该架构下如何工作。
var webpack = require('webpack') var path = require('path') var CleanWebpackPlugin = require('clean-webpack-plugin') var publicPath = '/' var hotMiddlewareScript = 'webpack-hot-middleware/client?reload=true' var devConfig = { debug: true, context: path.join(__dirname, '..'), entry: { auth: ['./client/auth', hotMiddlewareScript], dashboard: ['./client/dashboard', hotMiddlewareScript], user: ['./client/user', hotMiddlewareScript], }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, '../dist/client'), publicPath: publicPath }, plugins: [ new webpack.DefinePlugin({ 'process.env': { 'NODE_ENV': JSON.stringify('development'), 'STORE_STYLE': JSON.stringify('file'), } }), new webpack.optimize.OccurenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ], module: { preLoaders: [ { test: /\.js$/, loader: 'eslint-loader', exclude: /node_modules/ } ], loaders: [{ test: /\.js$/, loader: 'babel', query: { 'presets': ['es2015', 'stage-0'] }, include: [ path.join(__dirname, '../client'), path.join(__dirname, '../apis'), path.join(__dirname, '../utils') ], exclude: /node_modules/ },{ test: /\.(png|jpg)$/, loader: 'url?limit=8192&context=client&name=[path][name].[ext]' },{ test: /\.less$/, loader: 'style!css!less' }] }, eslint: { configFile: path.join(__dirname, '../.eslintrc.json') }, resolve: { extensions: ['','.js'] } } var devServerConfig = { name: 'server-side rendering', context: path.join(__dirname, '../'), target: 'node', entry: { apis: ['babel-polyfill', './apis'] }, output: { path: './dist/server', filename: 'apis.js', publicPath: '/', libraryTarget: 'commonjs2' }, plugins: [ new webpack.IgnorePlugin(/vertx/), new CleanWebpackPlugin(['dist'], { root: path.join(__dirname, '..') }) ], module: { preLoaders: [ { test: /\.js$/, loader: 'eslint-loader', exclude: /node_modules/ } ], loaders: [ { test: /\.js$/, loader: 'babel', query: { 'presets': ['es2015', 'stage-0'], }, include: [ path.join(__dirname, '../apis'), path.join(__dirname, '../utils') ], exclude: /node_modules/ }, { test: /\.json$/, loader: 'json-loader' } ] }, eslint: { configFile: path.join(__dirname, '../.eslintrc.json') }, resolve: { extensions: ['','.js'] } } module.exports = [devConfig,devServerConfig]
这是开发环境下的webpack配置,在entry中引入了需要生成client,即页面用到的js文件,并引入热启动加载的中间件。
在package.json中就可以去编写要使用的脚本,这里我使用的事npm-run-all 和 better-scripts:
{
"version": "1.0.0",
"license": "MIT",
"main": "server.js",
"scripts": {
"dev": "npm-run-all --sequential build:dev start-dev",
"start": "npm-run-all --sequential build:prod start-prod",
"test": "npm-run-all --sequential build:test start-test",
"build:dev": "better-npm-run build-dev",
"build:prod": "better-npm-run build-prod",
"build:test": "better-npm-run build-test",
"start-dev": "better-npm-run nodemon-dev",
"start-prod": "better-npm-run node-prod",
"start-test": "better-npm-run node-test",
"pm2-start": "pm2 start process.json",
"pm2-restart": "pm2 restart process.json"
},
"betterScripts": {
"build-dev": {
"command": "webpack --colors --config ./webpack/webpack.config.js",
"env": {
"NODE_ENV": "development",
"STORE_STYLE": "file",
"PORT": 5600
}
},
"nodemon-dev": {
"command": "nodemon server.js",
"env": {
"NODE_ENV": "development",
"STORE_STYLE": "file",
"PORT": 5600
}
},
"build-test": {
"command": "webpack --colors --config ./webpack/webpack.config.test.js",
"env": {
"NODE_ENV": "test",
"STORE_STYLE": "file",
"PORT": 8600
}
},
"node-test": {
"command": "node server.js",
"env": {
"NODE_ENV": "test",
"STORE_STYLE": "file",
"PORT": 8600
}
},
"build-prod": {
"command": "webpack --colors --config ./webpack/webpack.config.prod.js",
"env": {
"NODE_ENV": "production",
"STORE_STYLE": "file",
"PORT": 8600
}
},
"node-prod": {
"command": "node server.js",
"env": {
"NODE_ENV": "production",
"STORE_STYLE": "file",
"PORT": 8600
}
}
},
"devDependencies": {
"babel-core": "^6.11.4",
"babel-eslint": "^6.1.2",
"babel-loader": "^6.2.4",
"babel-polyfill": "^6.16.0",
"babel-preset-es2015": "^6.9.0",
"babel-preset-stage-0": "^6.5.0",
"better-npm-run": "0.0.13",
"clean-webpack-plugin": "^0.1.14",
"css-loader": "^0.23.1",
"es5-shim": "^4.5.9",
"es6-promise": "^3.2.1",
"es6-shim": "^0.35.1",
"eslint": "^3.2.2",
"eslint-loader": "^1.5.0",
"html-webpack-plugin": "^2.24.1",
"jquery": "^3.1.1",
"js-cookie": "^2.1.3",
"json-loader": "^0.5.4",
"less": "^2.7.2",
"n-zepto": "^1.2.0",
"nodemon": "^1.11.0",
"npm-run-all": "^3.1.1",
"webpack": "^1.13.2",
"webpack-dev-middleware": "^1.5.1",
"webpack-hot-middleware": "^2.12.2"
},
"dependencies": {
"axios": "^0.13.1",
"body-parser": "^1.15.2",
"captchapng": "0.0.1",
"clipboard": "^1.6.0",
"consolidate": "^0.14.5",
"cookie-parser": "^1.4.3",
"ejs": "^2.5.2",
"express": "^4.13.4",
"mongoose": "^4.9.1",
"querystringify": "0.0.4",
"react-cookie": "^0.4.8",
"uuid": "^3.0.1"
}
}
通过执行npm run yourcommand(如dev)去将项目启动。在启动的过程中,会通过npm run all 去执行两个步骤的操作,第一部分是生成页面使用的js文件,第二序列执行的结果会启动express服务,这里包括路由,接口和一些的数据持久化等。
在assets中将模板所需的文件(js css imgs)放置其中,设置其静态路径:
app.use('/assets', express.static(path.join(__dirname, 'assets')))
app.use(express.static(path.join(__dirname + '/')))
在views的模板中就可以使用以下路径去获得静态资源:
<link href="/assets/css/icons.css" rel="stylesheet" /> <!-- jQueryUI --> <link href="/assets/css/sprflat-theme/jquery.ui.all.css" rel="stylesheet" /> <!-- Bootstrap stylesheets (included template modifications) --> <link href="/assets/css/bootstrap.css" rel="stylesheet" /> <!-- Plugins stylesheets (all plugin custom css) --> <link href="/assets/css/plugins.css" rel="stylesheet" /> <!-- Main stylesheets (template main css file) --> <link href="/assets/css/main.css" rel="stylesheet" /> <!-- Custom stylesheets ( Put your own changes here ) --> <link href="/assets/css/custom.css" rel="stylesheet" />
<script src="/assets/plugins/core/moment/moment.min.js"></script> <script src="/assets/plugins/charts/sparklines/jquery.sparkline.js"></script> <script src="/assets/plugins/charts/pie-chart/jquery.easy-pie-chart.js"></script>
然后就是在express的路由中,将每个模块的router拆分,这样就可以互不影响:
require('./routes')(app)
module.exports = function (app) { app.use('/', require('./dashboard')) app.use('/auth', require('./auth')) app.use('/user', require('./user')) app.use('/init', require('./init')) }
这样就可以单独的写某个模块。
浙公网安备 33010602011771号