1.高效的開(kāi)發(fā)離不開(kāi)基礎(chǔ)工程的搭建。
2.近幾年來(lái)破托,前端的工作早已不再是切圖那么簡(jiǎn)單肪跋,項(xiàng)目比較大時(shí),可能會(huì)多人協(xié)同開(kāi)發(fā)土砂。模塊化州既、組件化谜洽、CSS預(yù)編譯等概念也成了經(jīng)常討論的話(huà)題。
前端自動(dòng)化(半自動(dòng)化)工程主要解決以下問(wèn)題:
- JavaScript吴叶、CSS代碼的合并和壓縮
- CSS 預(yù)處理:Less阐虚、Sass、Stylus的編譯
- 生成雪碧圖(CSS Sprite)
- ES6 轉(zhuǎn) ES5
- 模塊化
3.webpack打包后的代碼蚌卤,已經(jīng)不只是你寫(xiě)的代碼实束,其中夾雜了很多webpack自身的模塊處理代碼。因此造寝,學(xué)習(xí)webpack最難的是理解“編譯”這個(gè)概念磕洪,否則會(huì)一直存在一個(gè)疑問(wèn):為什么要這樣做吭练?
4.在業(yè)務(wù)中寫(xiě)的各種格式的文件诫龙,比如typescript、less鲫咽、jpg签赃,還有本章后面要介紹的.vue格式的文件。這些格式的文件通過(guò)特定的加載器(Loader)編譯后分尸,最終統(tǒng)一生成為.js锦聊、.css、.png等靜態(tài)資源文件箩绍。在webpack的世界里孔庭,一張圖片、一個(gè)css甚至一個(gè)字體材蛛,都稱(chēng)為模塊(Module)圆到,彼此存在依賴(lài)關(guān)系,webpack就是來(lái)處理模塊間的依賴(lài)關(guān)系的卑吭,并把它們進(jìn)行打包芽淡。
舉一個(gè)簡(jiǎn)單的例子,平時(shí)加載CSS大多通過(guò)<link>標(biāo)簽引入CSS文件,而在webpack里,直接在一個(gè).js文件中導(dǎo)入弓柱,比如:
import 'src/styles/index.css';
import 是 ES2015的語(yǔ)法钞钙,這里也可以寫(xiě)成 require('src/styles/index.css')。在打包時(shí)谅年,index.css會(huì)被打包進(jìn)一個(gè)js文件里,通過(guò)動(dòng)態(tài)創(chuàng)建<style>的形式來(lái)加載css樣式,當(dāng)然也可以進(jìn)一步配置纹笼,在打包編譯時(shí)把所有的css都提取出來(lái),生成一個(gè)css的文件苟跪。
5.webpack的主要使用場(chǎng)景是單頁(yè)面富應(yīng)用(SPA)廷痘。SPA通常是由一個(gè)html文件和一堆按需加載的js組成蔓涧,它的html結(jié)構(gòu)可能會(huì)非常簡(jiǎn)單,比如:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>webpack app</title>
<link rel="stylesheet" href="dist/main.css">
</head>
<body>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="app"></div>
<script type="text/javascript" src="dist/main.js"></script>
</body>
</html>
只有一個(gè)<div>節(jié)點(diǎn)笋额,所有的代碼都集成在了main.js文件中元暴,理論上它可以實(shí)現(xiàn)像知乎、淘寶這樣大型的項(xiàng)目兄猩。
6.在開(kāi)始講解webpack的用法前茉盏,先介紹兩個(gè)ES6 中的語(yǔ)法export和import,后面會(huì)大量使用枢冤。export和import是用來(lái)導(dǎo)出和導(dǎo)入模塊的鸠姨。一個(gè)模塊就是一個(gè)js文件,它擁有獨(dú)立的作用域淹真,里面定義的變量外部是無(wú)法獲取的讶迁。比如將一個(gè)配置文件作為模塊導(dǎo)出,示例代碼如下:
// config.js
var Config = {
version:'1.0.0'
};
export { Config };
// 或者 config.js
export var Config = {
version: '1.0.0'
};
//其他類(lèi)型(比如函數(shù)核蘸、數(shù)組巍糯、常量等)也可導(dǎo)出,比如導(dǎo)出一個(gè)函數(shù):
// add.js
export function add(a,b){
return a + b;
};
//模塊導(dǎo)出后客扎,在需要使用模塊的文件使用import再導(dǎo)入祟峦,就可以在這個(gè)文件內(nèi)使用這些模塊了。示例代碼:
//main.js
import {Config } from './config.js';
import { add } from './add.js';
console.log(Config); //{version : '1.0.0'}
console.log(add(1,1)); //2
以上幾個(gè)示例中徙鱼,導(dǎo)入的模塊名稱(chēng)都是在export的文件中設(shè)置的宅楞,也就是說(shuō)用戶(hù)必須預(yù)先知道這個(gè)名稱(chēng)叫什么,比如Config袱吆、add厌衙。而有的時(shí)候,用戶(hù)不想去了解名稱(chēng)是什么杆故,只是把模塊的功能拿來(lái)使用迅箩,或者想自定義名稱(chēng),這是可以使用export default 來(lái)輸出默認(rèn)的模塊处铛。示例代碼:
//config.js
export default {
version:'1.0.0'
};
//add.js
export default function(a,b){
return a + b ;
}
//main.js
import conf from './config.js';
import Add from './add.js';
console.log(conf); // {version:'1.0.0'}
console.log(Add(1,1)); // 2
//如果使用npm安裝了一些庫(kù)饲趋,在webpack中可以直接導(dǎo)入,示例:
import Vue from 'vue';
import $ from 'jquery';
上例分別導(dǎo)入了Vue和jQuery的庫(kù)撤蟆,并且命名為Vue和$奕塑,在這個(gè)文件中就可以使用這兩個(gè)模塊。export 和 import 還有其他的用法家肯,這里不做太詳細(xì)的介紹龄砰。
7.安裝webpack與 webpack-dev-server。確保意境安裝了最新的Node.js和NPM,并已經(jīng)了解NPM的基本用法换棚。
首先式镐,創(chuàng)建一個(gè)目錄,比如demo固蚤,使用NPM初始化配置:
npm init
執(zhí)行后娘汞,會(huì)有一些列選項(xiàng),可以按回車(chē)鍵快速確認(rèn)夕玩,完成后會(huì)在demo目錄生產(chǎn)一個(gè)package.json的文件你弦。
之后在本地局部安裝webpack:
npm install webpack --save-dev
--save-dev 會(huì)作為開(kāi)發(fā)依賴(lài)來(lái)安裝webpack。安裝成功后燎孟,在package.json中會(huì)多一項(xiàng)配置:
"devDependencies":{
"webpack" : "^2.3.2"
}
接著需要安裝webpack-dev-server禽作,它可以在開(kāi)發(fā)環(huán)境中提供很多服務(wù),比如啟動(dòng)一個(gè)服務(wù)器揩页、熱更新旷偿、接口代理等,配置起來(lái)也很簡(jiǎn)單碍沐。同樣狸捅,在本地局部安裝:
npm install webpack-dev-server --save-dev
安裝完成后衷蜓,最終的package.json文件內(nèi)容為:
{
"name" : "demo",
"version" : "1.0.0",
"description" : "",
"main" : "index.js",
"scripts" : {
"test" : "echo \"Error : no test specified \" && exit 1"
},
"author" : "",
"license" : "ISC",
"devDependencies" : {
“webpack” : "^2.3.2",
"webpack-dev-server" : "^2.4.2"
}
}
如果devDependencies中包含 webpack 和 webpack-dev-server累提,那么已經(jīng)安裝成功。
8.webpack核心概念磁浇。webpack就是一個(gè).js配置文件斋陪,你的架構(gòu)好或差都體現(xiàn)在這個(gè)配置里,隨著需求的不斷出現(xiàn)置吓,工程配置也是逐漸完善的无虚。
首先,在目錄DEMO 下創(chuàng)建一個(gè)js文件:webpack.config.js衍锚,并初始化它的內(nèi)容:
var config = {
};
module.exports = config;
這里的 module.exports = config; 相當(dāng)于 export default config;
由于目前還沒(méi)有安裝支持ES6的編譯插件友题,因此不能直接使用ES6的語(yǔ)法,否則會(huì)報(bào)錯(cuò)戴质。
然后在package.json的scripts里增加一個(gè)快速啟動(dòng)webpack-dev-server服務(wù)的腳本:
{
//...
"scripts" : {
"test" : "echo "Error: no test specified " && exit 1",
"dev" : "webpack-dev-server --config webpack.config.js"
},
//...
}
當(dāng)運(yùn)行 npm run dev 命令時(shí)度宦,就會(huì)執(zhí)行
webpack-dev-server --open --config webpack.config.js 命令。
其中告匠,--config 是指向 webpack-dev-server 讀取的配置文件路徑戈抄,這里直接讀取我們?cè)谏弦徊絼?chuàng)建的 webpack.config.js 文件。
--open 會(huì)在執(zhí)行命令時(shí)自動(dòng)在瀏覽器打開(kāi)頁(yè)面后专,默認(rèn)地址是 127.0.0.1:8080划鸽,不過(guò)IP和端口號(hào)都是可以配置的,如:
{
"scripts" : {
"dev" : "webpack-dev-server --host 172.172.172.1 --port 8888 --open --config webpack.config.js"
}
}
這樣訪問(wèn)地址就改為了 172.172.172.1:8888。一般在局域網(wǎng)下裸诽,需要讓其他同事訪問(wèn)時(shí)可以這樣配置嫂用。
webpack配置中最重要也是必選的兩項(xiàng)是入口(Entry)和 出口(Output)。入口的作用是告訴webpack從哪里開(kāi)始尋找依賴(lài)丈冬,并且編譯尸折,出口則用來(lái)配置編譯后的文件存儲(chǔ)位置和文件名。
在demo目錄下新建一個(gè)空的main.js作為入口的文件殷蛇,然后在webpack.config.js中進(jìn)行入口和輸出的配置:
var path = require('path');
var config = {
entry:{
main : './main'
},
output:{
path : path.join(_dirname, './dist'),
publicPath : '/dist/',
filename : 'main.js'
}
};
module.exports = config;
entry中的main就是我們配置的單入口实夹。webpack會(huì)從main.js文件開(kāi)始工作。output中path選項(xiàng)用來(lái)存放打包后的輸出目錄粒梦,是必填項(xiàng)亮航。publicPath指定資源文件引用的目錄,如果你的資源存放在CDN上匀们,這里可以填CDN的網(wǎng)址缴淋。filename用于指定輸出文件的名稱(chēng)。因此泄朴,這里配置的output意為打包后的文件會(huì)存儲(chǔ)為 demo/dist/main.js 文件重抖,只要在html 中引入它就可以了。在demo目錄下祖灰,新建一個(gè)index.html 作為我們 SPA 的入口:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>webpack APP</title>
</head>
<body>
<div id="app">
Hello World.
</div>
<script type="text/javascript" src="/dist/main.js"></script>
</body>
</html>
在終端執(zhí)行如下命令钟沛,就會(huì)自動(dòng)在瀏覽器中打開(kāi)頁(yè)面:
npm run dev
打開(kāi)dome/main.js文件,添加一行JavaScript代碼來(lái)修改頁(yè)面內(nèi)容:
document.getElementById('app').innerHTML = 'Hello webpack.';
保存文件局扶,回到剛才打開(kāi)的頁(yè)面恨统,發(fā)現(xiàn)頁(yè)面內(nèi)容已經(jīng)變?yōu)榱恕癏ello webpack”。注意三妈,此時(shí)并沒(méi)有刷新瀏覽器畜埋,就已經(jīng)自動(dòng)更新了,這就是webpack-dev-server 的熱更新功能畴蒲,它通過(guò)建立一個(gè)WebSocket 連接來(lái)實(shí)時(shí)響應(yīng)代碼的修改悠鞍。
9.學(xué)習(xí)webpack最難的是理解它“編譯”的概念。我們通過(guò)chrom瀏覽器開(kāi)發(fā)者工具的network視圖查看webpack編譯出的 /dist/main.js 文件模燥】Ъ溃可以看到有400多行。這里面很多都是webpack-dev-server的功能涧窒,只在開(kāi)發(fā)時(shí)有效心肪,生產(chǎn)環(huán)境下編譯就不會(huì)這么臃腫了。執(zhí)行下面的命令打包:
webpack --progress --hide-modules
這是會(huì)生成一個(gè) demo/dist/main.js 文件纠吴,只有很少的行數(shù)硬鞍。
10.上面通過(guò)配置入口(entry)和出口(Output)已經(jīng)可以啟動(dòng)webpack項(xiàng)目了,不過(guò)這并不是webpack的特點(diǎn),如果它只有這些功能固该,根本就不用這么麻煩锅减。webpack.config.js可以進(jìn)一步配置,來(lái)實(shí)現(xiàn)更強(qiáng)大的功能伐坏。
在webpack的世界里怔匣,每個(gè)文件都是一個(gè)模塊,比如.css桦沉、.js每瞒、.html、.jpg纯露、.less等剿骨。對(duì)于不同的模塊,需要用不同的加載器(Loaders)來(lái)處理埠褪,而加載器就是webpack最重要的功能浓利。通過(guò)安裝不同的加載器可以對(duì)各種后綴名的文件進(jìn)行處理,比如要寫(xiě)一些CSS樣式钞速,就要用到style-loader 和 css-loader贷掖。下面就通過(guò)NPM 來(lái)安裝它們:
npm install css-loader --save-dev
npm install style-loader --save-dev
安裝完成后,在webpack.config.js 文件里配置Loader渴语,增加對(duì).css 文件的處理:
var config = {
//...
module:{
rules:[
{
test: /\.css$/,
use:[
'style-loader',
'css-loader'
]
}
]
}
};
module.exports = config;
在module對(duì)象的rule屬性中可以指定一系列的loaders苹威,每一個(gè)loader都必須包含test和use兩個(gè)選項(xiàng)。這段配置的意思是說(shuō)遵班,當(dāng)webpack編譯過(guò)程中遇到 require()或 import 語(yǔ)句導(dǎo)入一個(gè)后綴名為 .css 的文件時(shí)屠升,先將它通過(guò) css-loader轉(zhuǎn)換潮改,再通過(guò)style-loader 轉(zhuǎn)換狭郑,然后繼續(xù)打包。 use選項(xiàng)的值可以是數(shù)組或字符串汇在,如果是數(shù)組翰萨,它的編譯數(shù)序就是從后往前。
在demo目錄下新建一個(gè)style.css的文件糕殉,并在main.js中導(dǎo)入:
/* style.css */
#app{
font-size:24px;
color:#f50;
}
// main.js
import './style.css';
document.getElementById('app').innerHTML = 'Hello webpack.';
重新執(zhí)行npm run dev 命令亩鬼,可以看到頁(yè)面中的文字已經(jīng)變成紅色,并且字號(hào)也變大了阿蝶。
11.可以看到雳锋,CSS是通過(guò)JavaScript動(dòng)態(tài)創(chuàng)建 <style> 標(biāo)簽來(lái)寫(xiě)入的,這意味著樣式代碼都已經(jīng)編譯在了main.js文件里羡洁,但在實(shí)際業(yè)務(wù)中玷过,可能并不希望這樣做,因?yàn)轫?xiàng)目大了樣式會(huì)很多,都放在JS里太占體積辛蚊,還不能做緩存粤蝎。這是要用到webpack的一個(gè)重要概念——插件(Plugins)。
webpack的插件功能很強(qiáng)大袋马,而且可以定制初澎。這里我們使用一個(gè) extract-text-webpack-plugin的插件來(lái)把散落在各地的css提取出來(lái),并生成一個(gè)main.css 的文件虑凛,最終在index.html里通過(guò)<link>的形式加載它碑宴。
通過(guò)NPM安裝 extract-text-webpack-plugin 插件:
npm install extract-text-webpack-plugin --save-dev
然后在配置文件中導(dǎo)入插件,并改寫(xiě)loader的配置:
//導(dǎo)入插件
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
//...
module:{
rules:[
{
test: /\.css$/,
use:ExtractTextPlugin.extract({
use:'css-loader',
fallback:'style-loader'
})
}
]
},
plugins:[
//重命名提取后的css文件
new ExtractTextPlugin("main.css")
]
};
module.exports = config ;
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>webpack APP</title>
<link rel="stylesheet" type="text/css" href="/dist/main.css">
</head>
.....
插件還可以進(jìn)行豐富的配置桑谍。重啟服務(wù)后墓懂,就可以看到<style>已經(jīng)沒(méi)有了,通過(guò)<link>引入的main.css 文件已經(jīng)生效霉囚。
webpack 雖然概念比較新捕仔,看似復(fù)雜,但它只不過(guò)是一個(gè)js配置文件盈罐,只要搞清楚入口(Entity)榜跌,出口(Output)、加載器(Loaders)和 插件(Plugins)這4個(gè)概念盅粪,使用起來(lái)就不那么困惑了钓葫。
12.單文件組件。之前票顾,在字符串模版template選項(xiàng)里拼寫(xiě)字符串DOM非常費(fèi)勁础浮,尤其是用""換行。Vue.js是一個(gè)漸進(jìn)式的JavaScript框架奠骄,在使用webpack 構(gòu)建Vue 項(xiàng)目時(shí)豆同,可以使用一種新的構(gòu)建模式:.vue 單文件組件。.vue 單文件組件就是一個(gè)后綴名為.vue 的文件含鳞,在webpack中使用vue-loader 就可以對(duì).vue 格式的文件進(jìn)行處理影锈。
一個(gè) .vue 文件一般包含3部分,即 <template>蝉绷、<script> 和 <style>鸭廷,如下所示:
<template>
<div>你好:{{ name }}</div>
</template>
<script>
export default {
props:{
name:{
type:String,
default:''
}
}
}
</script>
<style scoped>
div{
color:#f60;
}
</style>
在component.vue 文件中,<template></template>之間的代碼就是該組件的模板HTML熔吗,<style></style>之間的是CSS樣式辆床,示例中的<style>標(biāo)簽使用了scoped屬性,表示當(dāng)前的CSS只在這個(gè)組件有效桅狠,如果不加讼载,那么div的樣式會(huì)用到整個(gè)項(xiàng)目宵晚。<style>還可以結(jié)合CSS預(yù)編譯一起使用,比如使用 Less處理可以寫(xiě)成 <style lang="less">维雇。
13.使用.vue 文件需要先安裝 vue-loader淤刃、vue-style-loader 等加載器并做配置。因?yàn)橐褂肊S6 語(yǔ)法吱型,還需要安裝babel 和 babel-loader等加載器逸贾。
使用npm 逐個(gè)安裝以下依賴(lài):
npm install --save vue
npm install --save-dev vue-loader
npm install --save-dev vue-style-loader
npm install --save-dev vue-template-compiler
npm install --save-dev vue-hot-reload-api
npm install --save-dev babel
npm install --save-dev babel-loader
npm install --save-dev babel-core
npm install --save-dev babel-plugin-transform-runtime
npm install --save-dev babel-preset-es2015
npm install --save-dev babel-runtime
安裝完成后,修改配置文件webpack.config.js來(lái)支持對(duì) .vue文件及ES6的解析:
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
entry:{
main : './main'
},
output:{
path : path.join(__dirname, './dist'),
publicPath : '/dist/',
filename : 'main.js'
},
module:{
rules:[
{
test:/\.vue$/,
loader:'vue-loader',
options:{
loaders:{
css:ExtractTextPlugin.extract({
use:'css-loader',
fallback:'vue-style-loader'
})
}
}
},
{
test:/\.js$/,
loader:'babel-loader',
exclude:/node_modules/
},
{
test: /\.css$/,
use:ExtractTextPlugin.extract({
use:'css-loader',
fallback:'style-loader'
})
}
]
},
plugins:[
//重命名提取后的css文件
new ExtractTextPlugin("main.css")
]
};
module.exports = config;
vue-loader 在編譯.vue 文件時(shí)津滞,會(huì)對(duì)<template>铝侵、<script>、<style> 分別處理触徐,所以在vue-loader選項(xiàng)里多了一項(xiàng)options來(lái)進(jìn)一步對(duì)不同語(yǔ)言進(jìn)行配置咪鲜。比如在對(duì) css進(jìn)行處理時(shí),會(huì)先通過(guò)css-loader解析撞鹉,然后把處理結(jié)果再交給 vue-style-loader 處理疟丙。當(dāng)你的技術(shù)棧多樣化時(shí),可以給<template>鸟雏、<script>享郊、<style> 都指定不同的語(yǔ)言,比如<template lang="jade"> 和 <style lang="less"> 孝鹊, 然后配置loaders就可以了炊琉。
在demo目錄下新建一個(gè)名為.babelrc的文件,并寫(xiě)入babel的配置又活,webpack 會(huì)依賴(lài)此配置文件來(lái)用babel 編譯ES6 代碼:
{
"presets" : ["es2015"],
"plugins" : ["transform-runtime"],
"comments" : false
}
配置好這些后苔咪,就可以使用.vue 文件了。
每個(gè).vue 文件就代表一個(gè)組件柳骄,組件之間可以相互依賴(lài)团赏。
在工程目錄下新建一個(gè)app.vue的文件并寫(xiě)入以下內(nèi)容:
<template>
<div> Hello {{name}} </div>
</template>
<script>
export default {
data(){
return {
name: 'Vue.js'
}
}
}
</script>
<style scoped>
div{
color:#f60;
font-size:24px;
}
</style>
ES 6 語(yǔ)法提示:data () { } 等同于 data:function() { }
在<template>內(nèi)寫(xiě)的HTML寫(xiě)法完全同html文件,webpack最終會(huì)把它編譯為Render 函數(shù)的形式夹界。寫(xiě)在<style>里的樣式馆里,我們已經(jīng)用插件 extract-text-webpack-plugin 配置過(guò)了,最終會(huì)統(tǒng)一提取并打包在main.css 里可柿,因?yàn)榧恿藄cope 屬性,這部分樣式只會(huì)對(duì)當(dāng)前組件app.vue 有效丙者。
.vue 的組件是沒(méi)有名稱(chēng)的复斥,在父組件使用時(shí)可以對(duì)它自定義。寫(xiě)好了組件械媒,就可以在入口main.js 中使用它了目锭。打開(kāi)main.js 文件评汰,把內(nèi)容替換為下面的代碼:
// 導(dǎo)入 Vue 框架
import Vue from 'vue';
// 導(dǎo)入 app.vue 組件
import App from './app.vue';
// 創(chuàng)建 Vue 根實(shí)例
new Vue({
el: '#app',
render: h=> h (App)
})
執(zhí)行命令npm run dev,第一個(gè)Vue 工程就跑起來(lái)了痢虹。
打開(kāi)chrome調(diào)試工具被去,在elements 面板可以看到,<div id="app"> 已經(jīng)被組件替換成了:
<div data-v-381730fa> Hello Vue.js </div>
// 對(duì)應(yīng)的main.css 為:
div[data-v-381730fa]{
color:#f60;
font-size:24px;
}
之所以多了一串data-v-xxx 的內(nèi)容奖唯,是因?yàn)槭褂昧?lt;style scoped>的功能惨缆,如果去掉 scoped,就只剩下 <div> Hello Vue.js </div> 了丰捷。
解決npm 慢的問(wèn)題
可用 get命令查看registry
npm congfig get registry
原版結(jié)果為
http://registry.npmjs.org
用set命令換成阿里的鏡像就可以了
npm config set registry https://registry.npm.taobao.org
在執(zhí)行命令
npm install
接下來(lái)坯墨,在demo目錄下,再新建兩個(gè)文件title.vue 和 button.vue
// title.vue:
<template>
<h1>
<a :href="'#' + title "> {{ title }} </a>
</h1>
</template>
<script>
export default {
props:{
title:{
type:String
}
}
}
</script>
<style scoped>
h1 a{
color:#3399ff;
font-size:24px;
}
</style>
// button.vue:
<template>
<button @click="handleClick" :style="styles">
<slot></slot>
</button>
</template>
<script>
export default {
props:{
color:{
type:String,
default:'#00cc66'
}
},
computed:{
styles(){
return {
background:this.color
}
}
},
methods:{
handleClick(e){
this.$emit('click',e);
}
}
}
</script>
<style scoped>
button{
border:0;
outline:none;
color:#fff;
padding:4px 8px;
}
button:active{
position:relative;
top:1px;
left:1px;
}
</style>
改寫(xiě)根實(shí)例 app.vue 組件病往,把title.vue 和 button.vue 導(dǎo)入進(jìn)來(lái):
<template>
<div>
<v-title title="Vue組件化"></v-title>
<v-button @click="handleClick">點(diǎn)擊按鈕</v-button>
</div>
</template>
<script>
//導(dǎo)入組件
import vTitle from './title.vue';
import vButton from './button';
export default {
components:{
vTitle,
vButton
},
methods:{
handleClick(e){
console.log(e);
}
}
}
</script>
<style scoped>
div{
color:#f60;
font-size:24px;
}
</style>
導(dǎo)入的組件都是局部注冊(cè)的捣染,而且可以自定義名稱(chēng),其他用法和組件一致停巷。后面會(huì)基于webpack和單文件組件展開(kāi)耍攘。
ES 6 語(yǔ)法提示:
=> 是箭頭函數(shù)
render: h=> h(App) 等同于:
render : function (h) {
return h (App)
}components: {
vTitle,
vButton
}
等同于:
components:{
vTitle : vTitle,
vButton : vButton
}
對(duì)象字面量縮寫(xiě),當(dāng)對(duì)象的key 和 value 名稱(chēng)一致時(shí)畔勤,可以縮寫(xiě)成一個(gè)少漆。
14.用于生產(chǎn)環(huán)境。我們先對(duì)webpack 進(jìn)一步配置硼被,來(lái)支持更多常用的功能示损。安裝url-loader 和 file-loader 來(lái)支持圖片、字體等文件:
npm install --save-dev url-loader
npm install --save-dev file-loader
//webpack.config.js
var config = {
module:{
rules:[
{
test:/\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
loader:'url-loader?limit=1024'
}
}
當(dāng)遇到.gif嚷硫、.png检访、.ttf 等格式文件時(shí),url-loader會(huì)把它們一起編譯到dist 目錄下仔掸," ?limit=1024" 是指如果這個(gè)文件小余1kb脆贵,就以base64的形式加載,不會(huì)生成一個(gè)文件起暮。
找一張圖片卖氨,保存為 demo/images/image.png,并在app.vue 中加載它:
<template>
<div>
<v-title title="Vue組件化"></v-title>
<v-button @click="handleClick">點(diǎn)擊按鈕</v-button>
<p>
<img src="./images/image.png" style="width:200px;">
</p>
</div>
</template>
--save 和 --save-dev
在安裝包時(shí), 我們可以根據(jù)環(huán)境決定包的安裝效果. 假設(shè)我們要安裝express
1.執(zhí)行 npm i express --save則表示我想在生產(chǎn)環(huán)境中使用express, 同時(shí), express的版本信息會(huì)被寫(xiě)入package.json中的dependencies屬性中.
2.而執(zhí)行npm i express --save-dev 表示我想在開(kāi)發(fā)和測(cè)試環(huán)境中使用. express的版本信息會(huì)被寫(xiě)入package.json中的devDependencies屬性中.
3 --save可以簡(jiǎn)寫(xiě)為-S, --save-dev可以簡(jiǎn)寫(xiě)為-D.
查看包版本:
查看本地安裝的包 D:\source_code\vue-book-master\chapter 10>npm ls babel-loader chapter-10@1.0.0 D:\source_code\vue-book-master\chapter 10 `-- babel-loader@8.1.0 查看全局安裝的包 D:\source_code\vue-book-master\chapter 10>npm ls babel-loader -g D:\develop_soft\nodejs\node_global `-- (empty)
三個(gè)命令:
1.查看npm服務(wù)器上所有的包版本信息
npm view babel-loader versions
2.查看該包最新的版本是哪一個(gè)
npm view babel-loader version
3.可以查看該包所有版本负懦,以及更多的信息
npm info babel-loader
示例:
D:\source_code\vue-book-master\chapter 10>npm view babel-loader versions
[
'4.0.0', '4.1.0', '4.2.0', '4.3.0',
'5.0.0', '5.1.0', '5.1.2', '5.1.3',
'5.1.4', '5.2.0', '5.2.1', '5.2.2',
'5.3.0', '5.3.1', '5.3.2', '5.3.3',
'5.4.0', '5.4.1', '5.4.2', '6.0.0',
'6.0.1', '6.1.0', '6.2.0', '6.2.1',
'6.2.2', '6.2.3', '6.2.4', '6.2.5',
'6.2.6', '6.2.7', '6.2.8', '6.2.9',
'6.2.10', '6.3.0', '6.3.1', '6.3.2',
'6.4.0', '6.4.1', '7.0.0-alpha.1', '7.0.0-alpha.2',
'7.0.0-alpha.3', '7.0.0-beta.1', '7.0.0', '7.1.0',
'7.1.1', '7.1.2', '7.1.3', '7.1.4',
'7.1.5', '8.0.0-beta.0', '8.0.0-beta.1', '8.0.0-beta.2',
'8.0.0-beta.3', '8.0.0-beta.4', '8.0.0-beta.5', '8.0.0-beta.6',
'8.0.0', '8.0.1', '8.0.2', '8.0.3',
'8.0.4', '8.0.5', '8.0.6', '8.1.0'
]
D:\source_code\vue-book-master\chapter 10>npm view babel-loader version
8.1.0
D:\source_code\vue-book-master\chapter 10>npm info babel-loader
babel-loader@8.1.0 | MIT | deps: 5 | versions: 64
babel module loader for webpack
https://github.com/babel/babel-loader
dist
.tarball: https://registry.npm.taobao.org/babel-loader/download/babel-loader-8.1.0.tgz
.shasum: c611d5112bd5209abe8b9fa84c3e4da25275f1c3
dependencies:
find-cache-dir: ^2.1.0 loader-utils: ^1.4.0 mkdirp: ^0.5.3 pify: ^4.0.1 schema-utils: ^2.6.5
maintainers:
- danez <daniel@tschinder.de>
- existentialism <bng412@gmail.com>
- hzoo <hi@henryzoo.com>
- loganfsmyth <loganfsmyth@gmail.com>
dist-tags:
latest: 8.1.0 next: 8.0.0-beta.6 old: 5.4.2
published 2 months ago by existentialism <bng412@gmail.com>
D:\source_code\vue-book-master\chapter 10>
15.介紹打包上線(xiàn)前筒捺,先來(lái)分析webpack打包后的產(chǎn)物有哪些。
本書(shū)所介紹和使用的都是單頁(yè)面富應(yīng)用(SPA)技術(shù)纸厉,這意味著最終只有一個(gè)html的文件系吭,其余都是靜態(tài)資源。實(shí)際部署到生產(chǎn)環(huán)境時(shí)颗品,一般會(huì)將html 掛在后端程序下肯尺,由后端路由渲染這個(gè)頁(yè)面沃缘,將頁(yè)面所有的靜態(tài)資源(css、js则吟、image槐臀、icon、font等)單獨(dú)部署到CDN氓仲,當(dāng)然也可以和后端程序部署在一起水慨,這樣就實(shí)現(xiàn)了前后端完全分離。
我們?cè)趙ebpack的output 選項(xiàng)里已經(jīng)指定了path 和 publicPath寨昙,打完包后讥巡,所有的資源都會(huì)保存在 demo/dist 目錄下。
打包會(huì)用到下面兩個(gè)依賴(lài)舔哪,使用NPM安裝:
npm install --save-dev webpack-merge
npm install --save-dev html-webpack-plugin
為了方便開(kāi)發(fā)和生產(chǎn)環(huán)境的切換欢顷,我們?cè)赿emo目錄下再新建一個(gè)用于生產(chǎn)環(huán)境的配置文件 webpack.prod.config.js。
編譯打包捉蚤,直接執(zhí)行webpack 命令就可以抬驴。在package.json中,再加入一個(gè)build的快捷腳本用來(lái)打包:
"scripts" : {
"dev" : "webpack-dev-server --open --config webpack.config.js",
"build" : "webpack --progress --hide-modules --config webpack.prod.config.js"
}
先來(lái)看一下webpack.prod.config.js的代碼:
var webpack = require('webpack');
var HtmlwebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var merge = require('webpack-merge');
var webpackBaseConfig = require('./webpack.config.js');
//清空基本配置的插件列表
webpackBaseConfig.plugins = [ ];
module.exports = merge(webpackBaseConfig,{
output:{
publicPath : '/dist/',
//將入口文件重命名為帶有20位hash值的唯一文件
filename: '[name].[hash].js'
},
plugins:[
new ExtractTextPlugin({
// 提取 css缆巧,并重命名為帶有20位hash值的唯一文件
filename : '[name].[hash].css',
allChunks : true
}),
// 定義當(dāng)前node 環(huán)境為生產(chǎn)環(huán)境
new webpack.DefinePlugin({
'process.env' : {
NODE_ENV : '"production"'
}
}),
// 壓縮js
new webpack.optimize.UglifyJsPlugin({
compress : {
warnings : false
}
}),
// 提取模板布持,并保存入口 html文件
new HtmlWebpackPlugin({
filename : '../index_prod.html',
template : './index.ejs',
inject : false
})
]
});
上面安裝的 webpack-merge 模塊就是用于合并兩個(gè)webpack 的配置文件,所以prod 的配置是在webpack.config.js 基礎(chǔ)上擴(kuò)展的陕悬。靜態(tài)資源在大部分場(chǎng)景下都有緩存(304)题暖,更新上線(xiàn)后一般都希望用戶(hù)能及時(shí)地看到內(nèi)容,所以給打包后的css和js文件的名稱(chēng)都加了20位的hash值捉超。這樣文件名就唯一了(比如 main.b3dd20e2dae9d76af86b.js)胧卤,只要不對(duì)html文件設(shè)置緩存,上線(xiàn)后立即就可以加載最新的靜態(tài)資源拼岳。
html-webpack-plugin 是用來(lái)生成html 文件的枝誊,它通過(guò)template 選項(xiàng)來(lái)讀取指定的模板 index.ejs,然后輸出到filename 指定的目錄惜纸,也就是demo/index_prod.html叶撒。模板 index.ejs 動(dòng)態(tài)設(shè)置了靜態(tài)資源的路徑和文件名,代碼如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>webpack App</title>
<link rel="stylesheet" href="<%= htmlwebpackPlugin.files.css[0] %>">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="<%= htmlwebpackPlugin.files.js[0] %>"></script>
</body>
</html>
最后在終端運(yùn)行 npm run build耐版,等待一會(huì)就會(huì)完成打包祠够,成功后在demo下會(huì)生成一個(gè)dist的目錄,里面就是打包完的所有靜態(tài)資源椭更。
ejs 是一個(gè)JavaScript 模板庫(kù)哪审,用來(lái)從JSON 數(shù)據(jù)中生成HTML 字符串,常用于 Node.js虑瀑。
webpack除了上述內(nèi)容外湿滓,和有很多高級(jí)的配置和豐富的插件及加載器,可查閱webpack文檔:https://webpack.js.org/
本章代碼:https://github.com/icarusion/vue-book
vue-book 下的demo目錄下執(zhí)行 npm install 命令會(huì)自動(dòng)安裝所有的依賴(lài)舌狗,然后執(zhí)行 npm run dev 啟動(dòng)服務(wù)叽奥。