手动搭建vue+node单页面(一)
这里提供手动搭建vue单页面开发生产环境,并使用node写后台代码,仅供小白参考;
代码虽然没多少,但牵扯的知识很多,需要逐个研究;
后续内容《手动搭建vue+node单页面(二)》
https://segmentfault.com/a/11...
项目地址:https://github.com/liubingyan...
内容提要:vue2,webpack,express,router,jsonp,这一章会从0到开发环境,生产环境的搭建:
思路: 先实现webpack单页面的demo -> 然后实现express服务下的开发环境 -> 再实现开发·生产环境的切换 -> 最后做业务相关的页面和后端开发
一、创建项目:
1.初始化项目:在桌面新建文件夹test,在test目录下命令行输入npm init -y;
2.test下创建src文件夹(前端所有代码);
build文件夹(打包相关的webpack配置文件);
service文件夹(存放后端代码);
data文件夹(存放json数据);
server.js(node服务)
二、下面我们先做单页面,先不管服务的事情
在src目录中创建views(存放所有.vue组件),router(存放前端路由配置),store(存放vuex配置),man.js(单页面入口文件),app.vue(单页面首页组件),test下创建index.html作为载体。
接下来要做几件事完成单页面demo:
(1)编写入口文件main.js
//main.js const Vue from 'vue' const App from './app' new Vue({ el:'#app', render:h=>h(App) })
(2)单页面主体app.vue;
//app.vue <template> <div> {{msg}} </div> </template> <script> export default{ data(){ return { msg:'this is my app!' } } } </script> <style lang='less'> </style>
(3)接下来是配置文件:在build文件夹中创建webpack.config.js
//webpack.config.js const path = require('path') module.exports = { mode:'development',//webpack4新加的,不写会报黄 entry: { main: path.resolve(__dirname, '../src/main.js') }, output: { path: path.resolve(__dirname, '../dist'), publicPath: 'http://localhost:3000/', filename: '[name].js' }, module: { rules: [{ test: /\.vue$/, loader: 'vue-loader', options: { loaders: { 'less': [ 'vue-style-loader', 'css-loader', 'less-loader' ] } } }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },] }, resolve: { alias: {//开发环境使用vue.esm.js',官网有说明 'vue$': 'vue/dist/vue.esm.js' }, //reuqire加载文件会自动为以下后缀的文件(如:./app.vue可以写成./app了) extensions: ['*', '.js', '.vue', '.json'] }, }
接下来就是要启动项目了,不过要先安装各种插件
vue vue-loader webpack css-laoder sass-loader vue-style-loader babel-loader ````
不全,缺什么根据提示慢慢装
应为最终我们启动项目是用server.js启动,所以在这里我们这样写
//server.js const webpack=require('webpack') const webpackConfig=require('./build/webpack.config') webpack(webpackConfig,function(err,stats){ if(err) throw err //输出打包信息(不用在意这些细节) process.stdout.write(stats.toString({ colors: true, modules: false, children: false, chunks: false, chunkModules: false }) + '\n\n') })
然后执行打包(在test目录下)
node server
爆红就好好看看是语法错误还是少插件,一会儿就能解决。
看下效果,忘记,index.html要先写成:
//index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id='app'></div> </body> </html> <script type="text/javascript" src="./dist/main.js"></script>
打开index.html看看效果。
三、开始实现express启服和热加载
接下来用express启服,同时实现webpack的热加载和server.js的热加载;
1.修改配置server.js
//server.js const webpack=require('webpack') const webpackConfig=require('./build/webpack.config') //dev和hot用来实现前端的热加载 const webpackDevMiddleware = require('webpack-dev-middleware') const webpackHotMiddleware = require('webpack-hot-middleware') const express=require('express') const path=require('path') const app=express() const compiler = webpack(webpackConfig)//删除了打印的回调函数,加上的话这里会执行两遍打包,不晓得为啥 app.use(webpackDevMiddleware(compiler,{ // public path should be the same with webpack config //在项目中这样的路径都会配置到统一的文件中 publicPath: 'http://localhost:3000/', noInfo: true, stats: { colors: true } })) app.use(webpackHotMiddleware(compiler)) app.listen(3000,function(){ console.log('App is now running on port 3000!'); })
2.修改两个地方:webpack配置和index.html
// webpack.config.js const path = require('path') const webpack=require('webpack') const htmlPlugin=require('html-webpack-plugin') //增加页面热加载字段,添加到entry中(固定写法) const hotMiddlewareScript = 'webpack-hot-middleware/client?reload=true' module.exports = { mode: 'development', entry: { //就是这样写就对 了 main: [path.resolve(__dirname, '../src/main.js'),hotMiddlewareScript] }, output: { path: path.resolve(__dirname, '../dist'), publicPath: 'http://localhost:3000/', filename: '[name].js' }, module: { rules: [{ test: /\.vue$/, loader: 'vue-loader', options: { loaders: { 'scss': [ 'vue-style-loader', 'css-loader', 'less-loader' ] } } }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, ] }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' }, extensions: ['*', '.js', '.vue', '.json'] }, //新增html插件,生成main.js的同时生成index.html plugins:[ new htmlPlugin({ template:'index.html' }), //热加载需要使用这个插件才起作用 new webpack.HotModuleReplacementPlugin(), ] }
然后index.html改动就是删除自己写的script标签就好。
3.启动项目之前全局安装一个插件:(前端有了热加载,这个是为了后端的热加载,修改服务或者打包配置文件不用手动重启服务。)
npm i supervisor -g
然后修改package.json中的scripts
//package.json "scripts": { "test": "echo \"Error: no test specified\" && exit 1", //这句话是说:监控(-w)后定义的文件或者文件夹 -e表示-w监控的文件夹中的js文件发生变化时重启server.js "start": "supervisor -w server,build,server.js -e js server"
},
4.接下来激动人心的时刻,启动:
npm run start
打开localhost:3000
按下f12看看有没有报错,当当当当,没有报错,现在已经完成了一个简单但功能完善的开发环境;
四、署下生产环境
部署生产环境我们要做几件事:
1.build新建config.js,配置一些通用设置;
2.build新建webpack.config.dev.js,区分开发模式和生产模式的配置,其实可以写在一个文件中,弊端就是代码太长,而且开发模式require()的组件比较多,生产模式没必要加载,所以分开;
3.修改server.js,webpack.js和package.json文件;
我们先修改package.json
//通过设置node环境中process.ENV属性,来告诉webpack和server应该运行在哪个环境,cross-env NODE_ENV就是用来设置process.ENV的; //package.json "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "supervisor -w server,build,server.js -e js,html server", "dev": "cross-env NODE_ENV=development supervisor -w server,build,server.js -e js,html server", "pro": "cross-env NODE_ENV=production node server" },
cross-env需要安装下
npm i cross-env -save
再运行开发环境就用npm run dev ,生产就用npm run pro
接下来在build文件夹下创建并配置config.js
//config.js //简单配置够用就好,完整的配置可以到vue全家桶中学习 const path=require('path') let isdev=process.env.NODE_ENV=='development'?true:false let config={ isdev:isdev, publicPath:'http://localhost:3000/', port:'3000' } module.exports=config
在build下创建并编辑webpack.dev.config.js(把之前的webpack.config.js复制一下)
//webpack.config.dev.js(只展示不同的地方) //.... //新增通用配置文件 const config = require('./config') //.... output: { path: path.resolve(__dirname, '../dist'), publicPath: config.publicPath,//就是修改了输出的公网路径为配置文件中的路径 filename: '[name].js' }, plugins: [ new webpack.HotModuleReplacementPlugin(), //删除html模板(后面会解释) //new htmlPlugin({ // template:'index.html' // }), ] //....
接下来修改webpack.config.js为生产环境配置(同样只列出不同的地方)
//webpack.config.js const config = require('./config') //删除热加载 //const hotMiddlewareScript = 'webpack-hot-middleware/client?reload=true' //新增文件清除插件 const cleanWebpackPlugin = require('clean-webpack-plugin') //.... entry: { main:path.resolve(__dirname, '../src/main.js')//取消热加载 }, output: { path: path.resolve(__dirname, '../dist'), publicPath: config.publicPath, filename: '[name].js' }, //.... resolve: { alias: { 'vue$': 'vue/dist/vue.min.js'//生产使用压缩的vue文件 }, extensions: ['*', '.js', '.vue', '.json'] }, plugins: [ //删除热加载 //new webpack.HotModuleReplacementPlugin(), //删除html模板(后面会解释) //new htmlPlugin({ // template:'index.html' // }), //增加dist删除选项 new cleanWebpackPlugin(['dist'], { "root": path.resolve(__dirname, '../'), }) ] //....
最后修改server文件,觉得长可以试着分成开发生产两个文件
//server.js const webpack = require('webpack') const webpackConfig = require('./build/webpack.config') const webpackDevConfig = require('./build/webpack.config.dev') const webpackDevMiddleware = require('webpack-dev-middleware') const webpackHotMiddleware = require('webpack-hot-middleware') const express = require('express') const path = require('path') //新增config和swig插件 const config = require('./build/config') const swig = require('swig') const app = express() //swig一款js模板引擎,是服务端向客户端返回html的一种方式,swig只是众多引擎中的一种; //这里通过node向页面返回html,而不是直接访问dist中的index.html,所以到这里已经把webpack中的html模板删掉了; //如果使用webpack使用html插件,在切换生产和开发需要手动修改html的script; app.engine('html', swig.renderFile); app.set('view engine', 'html'); app.set('views', path.resolve(__dirname, './')); app.get('/', function(req, res) { res.type('text/html'); res.render('index'); }); if (config.isdev) { console.log('server运行在开发环境') const compiler = webpack(webpackDevConfig) app.use(webpackDevMiddleware(compiler, { // public path should be the same with webpack config publicPath: 'http://localhost:3000/', stats: { colors: true } })) app.use(webpackHotMiddleware(compiler)) } else { console.log('server运行在生产环境') webpack(webpackConfig, function(err, stats) { if (err) throw err //输出打包信息(这里又可以用了) process.stdout.write(stats.toString({ colors: true, modules: false, children: false, chunks: false, chunkModules: false }) + '\n\n') app.use(express.static(path.resolve(__dirname, './dist'))) }) } app.listen(config.port, function() { console.log('App is now running on port 3000!'); })
运行之前先装下swig插件,同时修改下index.html,手写
//index.html <script type="text/javascript" src="main.js"></script>
到目前为止的目录结构:
环境搭建完成了,业务代码及后端逻辑下篇再讲;
《手动搭建vue+node单页面(二)》
https://segmentfault.com/a/11...