所以以上步骤省略,
这里我们需要创建一个与之前类似的基础项目结构,
先上package.json
这里涉及到了一个与普通环境不同的地方
在script中的启动指令需要有两个
我们通过两个关键字来区分生产环境与发布代码的环境 dev代表生产环境,build代表发布环境
那么我们先解释一下生产环境和发布环境的区别:
生产环境是程序员开发项目时候所使用的一种环境,这里面方便程序员的开发体验将会加入很多自动化的功能
比如,编写代码的界面自动刷新,css兼容性的补全,还有开发者新创建模块的时候代码会自动生成文件等功能,
但是这些功能在项目发布到线上服务器之后是都不需要的,如果手动添加到界面与逻辑代码中,发布项目的时候再手动去掉
是非常痛苦的一件事,还有一点,当项目发布之后大量的js代码以及css代码是需要做压缩和混淆的,所以我们实际上还需要
一个环境叫做发布环境,这个环境执行一套相同的代码但是需要两种结果,所以我们把生产和发布分成两个环境,但是我们
没有必要创建两个项目来开发一套代码,所以这个时候起步就要把两种环境的标示分配好
了解了这一点之后
我们在www文件中通过一行代码来识别当前的是生产环境还是发布环境
//识别环境标示(启动服务传递的参数 dev为生产环境,build为构建发布环境)
process.env.NODE_ENV = process.argv.splice(2);
通过process.argv可以的到启动服务时传递的参数这样我们就可以根据不同的启动指令来做出判断
接下来我们看一下这个项目的文件结构
整个项目的服务端配置代码都在bin文件夹中
public文件夹下放置编译好的项目文件
src中是开发代码的目录结构
这里再做一下编译和开发的代码区别
由于前端程序员以及前端架构日趋复杂化,
在开发项目的时候有很多的程序员会使用除了原生代码之外的开发语种,
比如scss,ts,less,sass等
这些代码是浏览器直接执行不了的,所以在使用的时候还需要把她们编译成原生的css,js,html等
如果在线上执行的时候每次都要把代码转译是一个效率极低的选择,所以我们多了一套叫做源代码的东西
在开发的时候程序员可以按照自己最擅长的语种去开发,
开发结束后项目运行的还是html,css和js
所以src和public一个是写代码用的结构,一个是生成代码用的结构,
这里如果你是一个java程序员,将很容易理解这个编译和执行的流程
然后我们着重的说明一下配置文件的部分:
今天的配置文件中出了app.js pakage.js postcss.config.js webpack.config.js
多出来一个page.config.js
这个文件不是官方的插件,而是笔者编写的一个配置文件,
他的作用是用来生成一种固定的文件结构,
我们在开发webpack项目的时候
js,css等文件是有一套固定结构的,我们可以针对自己熟悉的结构自己定制一套生成文件系统
这样可以通过工具来把重复的代码自动的生成,我们就不需要在创建文件上而浪费时间,
所以page.config.js主要功能是根据内部的结构在src下生成对应的html,js,css文件
并且生成初始结构
文件结构如上图,
这里需要说明的是,小白们不要傻傻的以为这个文件加上就会自带这个功能,
功能是针对你自己的项目结构自己编写代码得到的,
那么我们的配置文件是怎么执行的呢?
有两个入口
第一个就是当启动服务器的过程中,
代码会自动检测,如果当前是生产环境,就会读取配置文件,并且根据里面的json结构来扫描src下的文件,如果配置文件中
有文件结构中没有的节点就会分别在js html css中生成与节点同名的文件
第二个就是当我们在编写代码的时候,这个时候有可能服务器还在启动中,那么不需要重新启动服务器,只需要在这个json的结构中国年
继续向下添加节点,当使用crtl+s保存文件之后代码会自动检测文件变化并且在文件夹中生成指定文件,
能够实现这个类似webpack的功能全部依赖于nodejs这个强大的代码环境
在我们熟悉的fs模块中有一个watch方法,就是可以检测文件改动的方法,通过这个模块我们可以实现当改动文件时触发相应的代码执行
这里的流程就是
当文件发生变化的时候我们就读取文件的内容执行makeUserDir的内容
这里有人会问为什么要用fs读取文件而不用require来直接获取内容,
这是因为require是从缓存中读取数据的,我们启动服务器之后后续改动文件的化不会触发缓存的变化,
我们就直接读取文件物理数据来拿到最新的配置内容了
接下来是webpack的流程
这个是启动时,如果是生产环境就开启watch模式
我们这里依然使用socket来通知客户端刷新而不使用其他的插件
下面是webpack的配置文件
var htmlWebpackPlugin = require('html-webpack-plugin'); var extractWebpackPlugin = require('extract-text-webpack-plugin'); var OpenBrowserPlugin = require('open-browser-webpack-plugin'); var path = require('path'); var webpack = require('webpack'); var fs = require('fs'); var config = { entry:{ //加载hmrjs的源码 hmr:'./src/plugins/hmr.js', }, output:{ filename:'js/[name].js', path:path.join(__dirname,'public') //publicPath:'http://localhost:3000' }, externals: { 'vue': 'Vue', 'vue-router':'VueRouter', 'VueResource':'VueResource' }, module:{ rules:[ { test:/\.(gif|jpeg|jpg|png)\??.*$/, loader:'url-loader?limit=1000&name=img/[name].[ext]' }, { test:/\.(woff|svg|eot|ttf)\??.*$/, loader:'url-loader?limit=1000&name=fonts/[name].[ext]' }, { test:/\.html$/, loader:'html-loader' }, { test:/\.js$/, loader:'babel-loader' } ] }, plugins:[ new extractWebpackPlugin('css/[name].css'), ] } //如果是生产环境就加入自动打开浏览器,编译正常的css文件 if(process.env.NODE_ENV=='dev'){ config.plugins.unshift(new OpenBrowserPlugin({ url: 'http://localhost:3000/index' })); config.module.rules.unshift({ test:/\.css$/, loader:extractWebpackPlugin.extract({ fallback:'style-loader', use:'css-loader!postcss-loader' }) }); } //如果是发布环境就加入代码压缩 if(process.env.NODE_ENV=='build'){ config.module.rules.unshift({ test:/\.css$/, loader:extractWebpackPlugin.extract({ fallback:'style-loader', use:[{ loader:'css-loader', options:{minimize:true} },'postcss-loader'] }) }); config.plugins.push(new webpack.optimize.UglifyJsPlugin()); } var jsDocs = fs.readdirSync('./src/js'); for(var i=0;i