编译admin

因为之前都是在开发模式:localhost里,需要3000端口或8080端口启动才能看得到,到了生产环境下服务器就不再运行像npm run serve这种命令了,只会当成纯粹的HTML来访问。所以需要把moba-vue-admin和moba-vue-web都编译到server:moba-node里面的某个静态文件夹里面去,让它可以被访问到,这样的话访问 https://localhost:3000/web 就能访问到web端, https://localhost:3000/admin 就能访问到后台。

第一步:只开服务器https://localhost:3000,当然最简单的编译是直接编译:比如进入到admin文件夹里面去:`cd moba-vue-admin,执行npm run build`,就会开始编译,编译的话就会把我们写的所有源文件:src里面所有.vue和sass文件最终编译成纯粹的静态文件HTML,CSS和JS,然后就可以把这些静态文件上传到任意服务器,只要绑定域名开启端口就可以访问了。编译生成的文件夹dist里:
image.png

第一个chunk-vendors.js:引用的第三方库都放在里面有1M,app.js是自己写的js;同样chunk-vendors.css是第三方的css,自己写的只有0.5kb。

想要看后台界面,安装一个:npm i -g server,安装好后运行:serve dist直接启动这个dist,点击http://localhost:5000 就可以访问admin了,!!!记得前提是要开启服务器。

所以理论上把dist里面文件复制到任意一个地方,然后启动一个web服务器,就可以访问了。

但还有一个问题:js里可以看到https://localhost:3000/admin/api,这段代码写的应该是后台写的那个接口地址,如果这个放线上的话是访问不了的,因为线上的话是通过一个域名来访问,但是这个页面打开后是请求https://localhost:3000这个端口,显然不对:
image.png
所以到源代码里,在moba-vue-admin/src/http.js里的接口地址需要根据开发和编译来进行替换:

  1. const http = axios.create({
  2. baseURL: process.env.VUE_APP_API_URL || '/admin/api',
  3. // baseURL: 'http://localhost:3000/admin/api'
  4. })

在客户端一般是没有process变量的,但是用webpack打包cli之后,就有process环境变量的,process.env表示环境变量,里面有一个VUE_APP_API_URL这个变量,才是我们真正的接口地址,如果有VUE_APP_API_URL就用它,如果没有就用’/admin/api’这么个地址。即线上:http://yours.com/admin/api,本地:http://localhost:3000/admin/api,即前面的域名是什么,访问的接口域名就是什么,不会写死成localhost:3000。

第二步:去moba-vue-admin里添加一个环境变量文件.env.development,表示的是在我们开发模式下用到的vue的一些变量,变量名必须和上面写的变量名一样。

  1. VUE_APP_API_URL=http://localhost:3000/admin/api

因为开发环境下,我们用npm run serve启动localhost:8080或8081端口,这个时候直接去请求/admin/api的话是没有如何接口的,本地开发的话一定是localhost:3000/admin/api,我们默认的就用:baseURL: process.env.VUE_APP_API_URL || '/admin/api',和域名保持一致,但在本地开发时候,必须手动指定一个地址:VUE_APP_API_URL=http://localhost:3000/admin/api,即在开发环境下用VUE_APP_API_URL=http://localhost:3000/admin/api这个值覆盖掉baseURL: process.env.VUE_APP_API_URL || '/admin/api里VUE_APP_API_URL这个变量。不需要什么配置,只需要建一个.env.development文件,还有去http.js改成环境变量即可。

经过上面的操作后,再次npm run build下,编译出来的js里就不会再有localhost了。
image.png

第三步,把dist里面的文件复制一下,复制到服务器moba-node里新建文件夹admin里,表示后台管理界面的静态文件。然后去moba-node里面的index.js里,之前定义了上传文件静态文件托管,一样的道理,定义一个admin,app.use('/admin', express.static(__dirname + '/admin'))表示的是当前文件夹下面的admin文件夹,把它也静态文件托管。

这时去看一下http://localhost:3000/admin ,会发现有报错,是因为静态文件里面index.html里引用的css,js的地址全都是根/css或者是/js之类的,所以导致我们把它放到一个子目录之后,没有效果。
image.png

把index.js里:app.use('/admin', express.static(__dirname + '/admin'))前面的admin去掉,变成app.use('/', express.static(__dirname + '/admin')),浏览器输入http://localhost:3000这个根地址,不加任何接口,就会跳至:
image.png

输入正确用户名和密码就能打开了,也能看里面的数据。所以我们上面就把生成之后的静态文件放到了服务端代码里来了。但是直接把admin放到http://localhost:3000有点不安全,应该是http://localhost:3000/admin表示的是后台,http://localhost:3000/web表示的是web端,涉及到编译的时候,加一个输出文件的一个地址,或者说我们需要改的是:将生成的html里/css/改成/admin/css/,这样才比较合理:
image.png

现在需要去admin里面修改一下,新建一个vue.config.js配置文件,

  1. module.exports = {
  2. outputDir: __dirname + '/../moba-node/admin', //__dirname当前文件夹,/../往上退一级
  3. publicPath: process.env.NODE_ENV === 'production' ?
  4. '/admin/' : '/'
  5. }

vuecli官网里面有配置教程。publicPath表示的是生成的静态文件路径,就是上图中的href,默认里面是/,我们把它变成/admin/一个前缀,名字是子文件夹的名字,如果放到一个根目录的话就不用写这个名字。process.env.NODE_ENV === ‘production’:在它npm run build的时候,自动会把NODE_ENV变成production,然后就会使用这个/admin/,最终生成的文件的href地址就会/admin/css。否则开发环境npm run serve下的话就是/css。

还有一个outputDir,表示我们要输出到哪个文件夹,刚刚我们输出到的是默认文件夹dist再复制到moba-node/admin文件夹,有点麻烦,加outputDir这个操作直接把静态文件输出到指定的文件夹了。把admin和的 dist和node里的admin删了。

再去admin里npm run build,就将静态文件输出到指定的moba-node/admin文件夹里了:
image.png

所以用vuecli还是很方便的,可以很方便的控制生成到哪里,以及生成之后那个静态文件的根地址是什么,路径前缀是什么。

moba-node里就有admin了:
image.png

link href里也加上前缀/admin/了。回去把moba-node/inde.js里app.use('/', express.static(__dirname + '/admin'))改成app.use('/admin', express.static(__dirname + '/admin')):意思是将后面这个/admin文件夹托管到前面/admin这个前缀地址上面去:

输入http://localhost:3000/admin就正常跳至后台管理界面了。而不是刚刚的http://localhost:3000地址跳至后台界面,http://localhost:3000/admin这个地址更加符合一个正常网站的地址习惯:http://localhost:3000打开的应该是一个网站首页,而不是一个后台界面。

编译前端

编译前端也是一样的道理,复制vue.config.js,

  1. module.exports = {
  2. outputDir: __dirname + '/../moba-node/web',
  3. // publicPath: process.env.NODE_ENV === 'production'
  4. // ? '/web' //直接根地址,没必要publicPath
  5. // : '/' //如果是想访问http://localhost:3000/web才是移动端首页就要加这个配置
  6. }

还有把前端接口和地址也一并改了,把moba-vue-web/src/main.js里,

  1. import axios from 'axios'
  2. Vue.prototype.$http = axios.create({
  3. baseURL: process.env.VUE_APP_API_URL || '/web/api' // 或者,如果传了API_URL就用它:process.env.VUE_APP_API_URL;否则就用当前域名下的/web/api这个路径
  4. // baseURL: 'http://localhost:3000/web/api'
  5. })

为了开发同样在moba-vue-web里加.env.development:

VUE_APP_API_URL=http://localhost:3000/web/api

只用于开发环境,即我们npm run serve的时候,npm run build就不需要用到它了。

还有记得在moba-node/index.js中增加:app.use('/', express.static(__dirname + '/web')),表示我们把当前moba-node文件夹里面的web文件夹托管到根路径,直接访问http://localhost:3000的时候访问的其实就是web里面的东西。

接下来cd moba-vue-web,执行npm run build就可以了。http://localhost:3000打开了首页。
image.png

所以正式发布的话,根目录下的moba-vue-web就没太大必要了,要的是server里面有个编译生成的web就可以了。

总结:

http://localhost:3000访问的是前端页面,http://localhost:3000/admin访问的是后台,也不影响它的接口,因为接口就是3000里面的api才是接口,并不是3000这个根地址,

web里:
image.png

admin里:
image.png

这样就实现静态页面和接口共存,同时都属于一个服务端,当我们要发布的时候,只需要把server里面的东西发布上去就可以了。