最近想學(xué)一門前端框架锌奴,之前看了一些Angular1的教程,難學(xué)就不說(shuō)了萧朝,它的主人好像有了放棄他的意思岔留,推出了Angular2,基本上算是推翻了重來(lái)检柬,而且文檔還要越過(guò)GFW才能看献联,最近特別火的React也不錯(cuò),但是最后還是選了文檔十分友好的Vue,它借鑒了Angular1的指令和React組件化思想,在2.0版本中還加入了virtual DOM里逆。
這是一個(gè)漸進(jìn)式框架进胯,不同于jquery的直接操作dom,它是數(shù)據(jù)驅(qū)動(dòng)的原押,Vue 的核心庫(kù)只關(guān)注視圖層胁镐,是一個(gè)輕量級(jí)的框架,可以和其他庫(kù)相整合诸衔。廢話不多說(shuō)希停,大家可以去這個(gè)網(wǎng)站去看它的詳細(xì)文檔。
實(shí)踐才能真正掌握它署隘,vue可以像jquery一樣通過(guò)<script>
標(biāo)簽的方式寫到html中宠能,現(xiàn)在前端技術(shù)日新月異,在我看來(lái)磁餐,如果現(xiàn)在學(xué)習(xí)的話還不用新的東西违崇,還要學(xué)老一套的,遲早要被淘汰诊霹,這里我使用的是vue-cli羞延,使用webpack來(lái)搭建這個(gè)項(xiàng)目,對(duì)于webpack的介紹請(qǐng)看這里脾还,總之它非常好用伴箩,也是我要學(xué)習(xí)它的原因,這個(gè)腳手架工具鄙漏,這有vue-cli的安裝方法嗤谚,當(dāng)然最簡(jiǎn)單的方法就是從github上直接copy下來(lái),這里是連接怔蚌,下載下來(lái)后在解壓后的文件夾內(nèi)安裝依賴
$ npm install
最后的文件目錄是這樣的
下面就開(kāi)始分析這些目錄中的這些文件
首先要說(shuō)的是
package.json
這個(gè)文件巩步,這是整個(gè)文件的靈魂啊,
{
"name": "example",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "xxx",
"private": true,
"scripts": {
"dev": "node build/dev-server.js",
"build": "node build/build.js",
"lint": "eslint --ext .js,.vue src"
},
"dependencies": {
//真的依賴桦踊。椅野。
"vue": "^2.0.1"
},
"devDependencies": {
//太多省略了
//這里是開(kāi)發(fā)時(shí)的依賴
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
}
}
這個(gè)文件是可以通過(guò)npm init
控制行命令生成,前提是你電腦得裝了node籍胯,如果沒(méi)有的話竟闪,這篇文章可以先不用看了,先去裝個(gè)node吧杖狼。
package.json
這個(gè)文件是json格式的文件炼蛤,它的每一個(gè)鍵值對(duì),儲(chǔ)存了這個(gè)項(xiàng)目的數(shù)據(jù)本刽, "dependencies"
和"devDependencies"
是這個(gè)項(xiàng)目所要用到的依賴包鲸湃,什么是依賴包呢,就拿就jquery和bootstrap說(shuō)吧子寓,要想使用bootstrap就要先引入jquery暗挑,而這就產(chǎn)生了依賴關(guān)系,webpack可以將所要用到的各種資源文件包括js斜友、css等文件打包炸裆,好處就是將繁雜的資源引用打包,減少http請(qǐng)求數(shù)鲜屏,壓縮資源存儲(chǔ)空間烹看,加快網(wǎng)頁(yè)訪問(wèn)速度。
回到這個(gè)文件洛史,"dependencies"
主要是網(wǎng)頁(yè)所要用到的依賴包惯殊,我們演示的是vue示例,當(dāng)然就有"vue": "^2.0.1"
這一條了也殖,后面的是依賴包的版本號(hào)土思;而"devDependencies"
是開(kāi)發(fā)時(shí)的包依賴,比如我們要想在js配置文件中使用es6的語(yǔ)法就需要引用barbel依賴忆嗜,要模擬服務(wù)器就要使用express模塊等等己儒,但是他們只是開(kāi)發(fā)的時(shí)候用,資源打包編譯過(guò)后就不用這些組件或模塊了捆毫,因此寫在"devDependencies"
下邊闪湾。
node是一個(gè)js的運(yùn)行環(huán)境,npm是隨著node一起安裝的包管理工具绩卤,正確裝完node之后就可以使用命令行指令了途样,通過(guò)node指令可以執(zhí)行js文件
$ node xx.js //執(zhí)行某文件
而npm指令可以執(zhí)行package.json
里定義的相關(guān)操作
"scripts": {
"dev": "node build/dev-server.js",
"build": "node build/build.js",
"lint": "eslint --ext .js,.vue src"
},
$ npm installl
//把dependencies和devDependencies中的依賴下載安裝到node_modules文件夾
$ npm run-script dev
//也可以這么寫
$ npm run dev
//執(zhí)行package.json中的dev這個(gè)指令,在這里等同于
$ node build/dev-server.js
//這里可以自己隨便寫濒憋,引號(hào)里的是要在命令行執(zhí)行的指令
打開(kāi)文件夾娘纷,在這個(gè)文件下打開(kāi)命令行,shift
+鼠標(biāo)右鍵打開(kāi)命令行
我們執(zhí)行
$ npm run dev
這樣就成功的在瀏覽器中顯示了
可是對(duì)這個(gè)過(guò)程是怎么實(shí)現(xiàn)的依然一頭霧水
那我們就從這個(gè)指令開(kāi)始吧$ npm run dev
跋炕,之前說(shuō)了赖晶,這個(gè)指令就是執(zhí)行這個(gè)目錄build/下的dev-server.js文件
build文件夾
build文件目錄是這樣的
|-build
|-build.js
|-check-versions.js
|-dev-client.js
|-dev-server.js
|-utils.js
|-webpack.base.conf.js
|-webpack.dev.conf.js
|-webpack.prod.conf.js
(瞬間感覺(jué)壓力巨大,但是本著不能輕言放棄的原則辐烂,我會(huì)堅(jiān)持下去的)
打開(kāi)dev-server.js
這個(gè)文件遏插,有點(diǎn)大,如果你能一條條讀下來(lái)纠修,相信會(huì)收獲很多的
require('./check-versions')()
//這里是將package.json中的engine要求的node胳嘲,npm版本號(hào)和本地版本相比對(duì)
//如果不符合就會(huì)在命令行用紅色和綠色的文字發(fā)出警告
var config = require('../config')
//引入另一個(gè)文件夾config的index.js總之是一些配置組成的對(duì)象
if (!process.env.NODE_ENV) process.env.NODE_ENV = config.dev.env
//process是nodejs中的一個(gè)全局對(duì)象,可以看作一個(gè)進(jìn)程扣草,這個(gè)procee.env中保存著當(dāng)前shell的環(huán)境變量
//這里是如果這個(gè)環(huán)境變量中沒(méi)有NODE_ENV這個(gè)屬性了牛,就將它的值設(shè)為開(kāi)發(fā)模式development颜屠,相對(duì)的還有生產(chǎn)模式production
var path = require('path')
//這是node里的自帶模塊,用來(lái)處理相對(duì)路徑絕對(duì)路徑等
var express = require('express')
//這是一個(gè)基于nodejs的開(kāi)發(fā)框架鹰祸,可以搭建開(kāi)發(fā)環(huán)境下的服務(wù)器
var webpack = require('webpack')
//資源打包模塊
var opn = require('opn')
//一個(gè)用來(lái)打開(kāi)網(wǎng)頁(yè)甫窟、文件、可執(zhí)行文件的模塊
var proxyMiddleware = require('http-proxy-middleware')
//服務(wù)器中間件蛙婴,匹配對(duì)應(yīng)請(qǐng)求的的URL地址, 匹配的請(qǐng)求將被代理到目標(biāo)主機(jī)
var webpackConfig = require('./webpack.dev.conf')
//在大型項(xiàng)目中粗井,可能 webpack.config.js 會(huì)變得越來(lái)越臃腫,這個(gè)時(shí)候可以
//利用做 webpack-merge 插件街图。將配置定義在一個(gè)目錄下面的不同文件中
//然后通過(guò) webpack-merge 來(lái)合并成最終的配置浇衬。
var port = process.env.PORT || config.dev.port
// 設(shè)置端口號(hào)
var proxyTable = config.dev.proxyTable
//代理表,可以將復(fù)雜的url簡(jiǎn)寫
var app = express()
//實(shí)例化一個(gè)express
var compiler = webpack(webpackConfig)
//實(shí)例化一個(gè)compiler
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true,
chunks: false
}
})
var hotMiddleware = require('webpack-hot-middleware')(compiler)
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(context, options))
})
// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())
// serve webpack bundle output
app.use(devMiddleware)
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
module.exports = app.listen(port, function (err) {
if (err) {
console.log(err)
return
}
var uri = 'http://localhost:' + port
console.log('Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (process.env.NODE_ENV !== 'testing') {
opn(uri)
}
})
打開(kāi)build.js
這個(gè)文件
// https://github.com/shelljs/shelljs
require('./check-versions')()
//這里是將package.json中的engine要求的node餐济,npm版本號(hào)和本地版本相比對(duì)耘擂,如果不符合就會(huì)在命令行用紅色和綠色的文字發(fā)出警告
require('shelljs/global')
//可以在js文件中使用unix命令,比如mkdir絮姆、rm梳星、cp
env.NODE_ENV = 'production'
//這個(gè)是設(shè)置生產(chǎn)環(huán)境的標(biāo)志
var path = require('path')
//node自帶模塊,用來(lái)處理路徑
var config = require('../config')
//配置信息
var ora = require('ora')
//命令行工具
var webpack = require('webpack')
var webpackConfig = require('./webpack.prod.conf')
//載入webpack的配置文件
console.log(
' Tip:\n' +
' Built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
)
//命令行提示文字
var spinner = ora('building for production...')
spinner.start()
var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
rm('-rf', assetsPath)
mkdir('-p', assetsPath)
cp('-R', 'static/*', assetsPath)
//文件操作滚朵,創(chuàng)建目錄文件
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n')
})
//這里webpack將產(chǎn)生打包文件冤灾,webpack這個(gè)函數(shù)會(huì)根據(jù)配置文件生成匹配的打包文件
//這個(gè)回調(diào)函數(shù)將結(jié)果輸出在控制臺(tái)上
build文件夾
這個(gè)文件夾里的文件是和編譯相關(guān)的