1.高效的開發(fā)離不開基礎(chǔ)工程的搭建。
2.近幾年來,前端的工作早已不再是切圖那么簡單,項(xiàng)目比較大時,可能會多人協(xié)同開發(fā)。模塊化、組件化、CSS預(yù)編譯等概念也成了經(jīng)常討論的話題。
前端自動化(半自動化)工程主要解決以下問題:
- JavaScript、CSS代碼的合并和壓縮
- CSS 預(yù)處理:Less、Sass、Stylus的編譯
- 生成雪碧圖(CSS Sprite)
- ES6 轉(zhuǎn) ES5
- 模塊化
3.webpack打包后的代碼,已經(jīng)不只是你寫的代碼,其中夾雜了很多webpack自身的模塊處理代碼。因此,學(xué)習(xí)webpack最難的是理解“編譯”這個概念,否則會一直存在一個疑問:為什么要這樣做?
4.在業(yè)務(wù)中寫的各種格式的文件,比如typescript、less、jpg,還有本章后面要介紹的.vue格式的文件。這些格式的文件通過特定的加載器(Loader)編譯后,最終統(tǒng)一生成為.js、.css、.png等靜態(tài)資源文件。在webpack的世界里,一張圖片、一個css甚至一個字體,都稱為模塊(Module),彼此存在依賴關(guān)系,webpack就是來處理模塊間的依賴關(guān)系的,并把它們進(jìn)行打包。
舉一個簡單的例子,平時加載CSS大多通過<link>標(biāo)簽引入CSS文件,而在webpack里,直接在一個.js文件中導(dǎo)入,比如:
import 'src/styles/index.css';
import 是 ES2015的語法,這里也可以寫成 require('src/styles/index.css')。在打包時,index.css會被打包進(jìn)一個js文件里,通過動態(tài)創(chuàng)建<style>的形式來加載css樣式,當(dāng)然也可以進(jìn)一步配置,在打包編譯時把所有的css都提取出來,生成一個css的文件。
5.webpack的主要使用場景是單頁面富應(yīng)用(SPA)。SPA通常是由一個html文件和一堆按需加載的js組成,它的html結(jié)構(gòu)可能會非常簡單,比如:
<!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>
只有一個<div>節(jié)點(diǎn),所有的代碼都集成在了main.js文件中,理論上它可以實(shí)現(xiàn)像知乎、淘寶這樣大型的項(xiàng)目。
6.在開始講解webpack的用法前,先介紹兩個ES6 中的語法export和import,后面會大量使用。export和import是用來導(dǎo)出和導(dǎo)入模塊的。一個模塊就是一個js文件,它擁有獨(dú)立的作用域,里面定義的變量外部是無法獲取的。比如將一個配置文件作為模塊導(dǎo)出,示例代碼如下:
// config.js
var Config = {
version:'1.0.0'
};
export { Config };
// 或者 config.js
export var Config = {
version: '1.0.0'
};
//其他類型(比如函數(shù)、數(shù)組、常量等)也可導(dǎo)出,比如導(dǎo)出一個函數(shù):
// add.js
export function add(a,b){
return a + b;
};
//模塊導(dǎo)出后,在需要使用模塊的文件使用import再導(dǎo)入,就可以在這個文件內(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
以上幾個示例中,導(dǎo)入的模塊名稱都是在export的文件中設(shè)置的,也就是說用戶必須預(yù)先知道這個名稱叫什么,比如Config、add。而有的時候,用戶不想去了解名稱是什么,只是把模塊的功能拿來使用,或者想自定義名稱,這是可以使用export default 來輸出默認(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安裝了一些庫,在webpack中可以直接導(dǎo)入,示例:
import Vue from 'vue';
import $ from 'jquery';
上例分別導(dǎo)入了Vue和jQuery的庫,并且命名為Vue和$,在這個文件中就可以使用這兩個模塊。export 和 import 還有其他的用法,這里不做太詳細(xì)的介紹。
7.安裝webpack與 webpack-dev-server。確保意境安裝了最新的Node.js和NPM,并已經(jīng)了解NPM的基本用法。
首先,創(chuàng)建一個目錄,比如demo,使用NPM初始化配置:
npm init
執(zhí)行后,會有一些列選項(xiàng),可以按回車鍵快速確認(rèn),完成后會在demo目錄生產(chǎn)一個package.json的文件。
之后在本地局部安裝webpack:
npm install webpack --save-dev
--save-dev 會作為開發(fā)依賴來安裝webpack。安裝成功后,在package.json中會多一項(xiàng)配置:
"devDependencies":{
"webpack" : "^2.3.2"
}
接著需要安裝webpack-dev-server,它可以在開發(fā)環(huán)境中提供很多服務(wù),比如啟動一個服務(wù)器、熱更新、接口代理等,配置起來也很簡單。同樣,在本地局部安裝:
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就是一個.js配置文件,你的架構(gòu)好或差都體現(xiàn)在這個配置里,隨著需求的不斷出現(xiàn),工程配置也是逐漸完善的。
首先,在目錄DEMO 下創(chuàng)建一個js文件:webpack.config.js,并初始化它的內(nèi)容:
var config = {
};
module.exports = config;
這里的 module.exports = config; 相當(dāng)于 export default config;
由于目前還沒有安裝支持ES6的編譯插件,因此不能直接使用ES6的語法,否則會報(bào)錯。
然后在package.json的scripts里增加一個快速啟動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 命令時,就會執(zhí)行
webpack-dev-server --open --config webpack.config.js 命令。
其中,--config 是指向 webpack-dev-server 讀取的配置文件路徑,這里直接讀取我們在上一步創(chuàng)建的 webpack.config.js 文件。
--open 會在執(zhí)行命令時自動在瀏覽器打開頁面,默認(rèn)地址是 127.0.0.1:8080,不過IP和端口號都是可以配置的,如:
{
"scripts" : {
"dev" : "webpack-dev-server --host 172.172.172.1 --port 8888 --open --config webpack.config.js"
}
}
這樣訪問地址就改為了 172.172.172.1:8888。一般在局域網(wǎng)下,需要讓其他同事訪問時可以這樣配置。
webpack配置中最重要也是必選的兩項(xiàng)是入口(Entry)和 出口(Output)。入口的作用是告訴webpack從哪里開始尋找依賴,并且編譯,出口則用來配置編譯后的文件存儲位置和文件名。
在demo目錄下新建一個空的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會從main.js文件開始工作。output中path選項(xiàng)用來存放打包后的輸出目錄,是必填項(xiàng)。publicPath指定資源文件引用的目錄,如果你的資源存放在CDN上,這里可以填CDN的網(wǎng)址。filename用于指定輸出文件的名稱。因此,這里配置的output意為打包后的文件會存儲為 demo/dist/main.js 文件,只要在html 中引入它就可以了。在demo目錄下,新建一個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í)行如下命令,就會自動在瀏覽器中打開頁面:
npm run dev
打開dome/main.js文件,添加一行JavaScript代碼來修改頁面內(nèi)容:
document.getElementById('app').innerHTML = 'Hello webpack.';
保存文件,回到剛才打開的頁面,發(fā)現(xiàn)頁面內(nèi)容已經(jīng)變?yōu)榱恕癏ello webpack”。注意,此時并沒有刷新瀏覽器,就已經(jīng)自動更新了,這就是webpack-dev-server 的熱更新功能,它通過建立一個WebSocket 連接來實(shí)時響應(yīng)代碼的修改。
9.學(xué)習(xí)webpack最難的是理解它“編譯”的概念。我們通過chrom瀏覽器開發(fā)者工具的network視圖查看webpack編譯出的 /dist/main.js 文件??梢钥吹接?00多行。這里面很多都是webpack-dev-server的功能,只在開發(fā)時有效,生產(chǎn)環(huán)境下編譯就不會這么臃腫了。執(zhí)行下面的命令打包:
webpack --progress --hide-modules
這是會生成一個 demo/dist/main.js 文件,只有很少的行數(shù)。
10.上面通過配置入口(entry)和出口(Output)已經(jīng)可以啟動webpack項(xiàng)目了,不過這并不是webpack的特點(diǎn),如果它只有這些功能,根本就不用這么麻煩。webpack.config.js可以進(jìn)一步配置,來實(shí)現(xiàn)更強(qiáng)大的功能。
在webpack的世界里,每個文件都是一個模塊,比如.css、.js、.html、.jpg、.less等。對于不同的模塊,需要用不同的加載器(Loaders)來處理,而加載器就是webpack最重要的功能。通過安裝不同的加載器可以對各種后綴名的文件進(jìn)行處理,比如要寫一些CSS樣式,就要用到style-loader 和 css-loader。下面就通過NPM 來安裝它們:
npm install css-loader --save-dev
npm install style-loader --save-dev
安裝完成后,在webpack.config.js 文件里配置Loader,增加對.css 文件的處理:
var config = {
//...
module:{
rules:[
{
test: /\.css$/,
use:[
'style-loader',
'css-loader'
]
}
]
}
};
module.exports = config;
在module對象的rule屬性中可以指定一系列的loaders,每一個loader都必須包含test和use兩個選項(xiàng)。這段配置的意思是說,當(dāng)webpack編譯過程中遇到 require()或 import 語句導(dǎo)入一個后綴名為 .css 的文件時,先將它通過 css-loader轉(zhuǎn)換,再通過style-loader 轉(zhuǎn)換,然后繼續(xù)打包。 use選項(xiàng)的值可以是數(shù)組或字符串,如果是數(shù)組,它的編譯數(shù)序就是從后往前。
在demo目錄下新建一個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 命令,可以看到頁面中的文字已經(jīng)變成紅色,并且字號也變大了。
11.可以看到,CSS是通過JavaScript動態(tài)創(chuàng)建 <style> 標(biāo)簽來寫入的,這意味著樣式代碼都已經(jīng)編譯在了main.js文件里,但在實(shí)際業(yè)務(wù)中,可能并不希望這樣做,因?yàn)轫?xiàng)目大了樣式會很多,都放在JS里太占體積,還不能做緩存。這是要用到webpack的一個重要概念——插件(Plugins)。
webpack的插件功能很強(qiáng)大,而且可以定制。這里我們使用一個 extract-text-webpack-plugin的插件來把散落在各地的css提取出來,并生成一個main.css 的文件,最終在index.html里通過<link>的形式加載它。
通過NPM安裝 extract-text-webpack-plugin 插件:
npm install extract-text-webpack-plugin --save-dev
然后在配置文件中導(dǎo)入插件,并改寫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)沒有了,通過<link>引入的main.css 文件已經(jīng)生效。
webpack 雖然概念比較新,看似復(fù)雜,但它只不過是一個js配置文件,只要搞清楚入口(Entity),出口(Output)、加載器(Loaders)和 插件(Plugins)這4個概念,使用起來就不那么困惑了。
12.單文件組件。之前,在字符串模版template選項(xiàng)里拼寫字符串DOM非常費(fèi)勁,尤其是用""換行。Vue.js是一個漸進(jìn)式的JavaScript框架,在使用webpack 構(gòu)建Vue 項(xiàng)目時,可以使用一種新的構(gòu)建模式:.vue 單文件組件。.vue 單文件組件就是一個后綴名為.vue 的文件,在webpack中使用vue-loader 就可以對.vue 格式的文件進(jìn)行處理。
一個 .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只在這個組件有效,如果不加,那么div的樣式會用到整個項(xiàng)目。<style>還可以結(jié)合CSS預(yù)編譯一起使用,比如使用 Less處理可以寫成 <style lang="less">。
13.使用.vue 文件需要先安裝 vue-loader、vue-style-loader 等加載器并做配置。因?yàn)橐褂肊S6 語法,還需要安裝babel 和 babel-loader等加載器。
使用npm 逐個安裝以下依賴:
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來支持對 .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 文件時,會對<template>、<script>、<style> 分別處理,所以在vue-loader選項(xiàng)里多了一項(xiàng)options來進(jìn)一步對不同語言進(jìn)行配置。比如在對 css進(jìn)行處理時,會先通過css-loader解析,然后把處理結(jié)果再交給 vue-style-loader 處理。當(dāng)你的技術(shù)棧多樣化時,可以給<template>、<script>、<style> 都指定不同的語言,比如<template lang="jade"> 和 <style lang="less"> , 然后配置loaders就可以了。
在demo目錄下新建一個名為.babelrc的文件,并寫入babel的配置,webpack 會依賴此配置文件來用babel 編譯ES6 代碼:
{
"presets" : ["es2015"],
"plugins" : ["transform-runtime"],
"comments" : false
}
配置好這些后,就可以使用.vue 文件了。
每個.vue 文件就代表一個組件,組件之間可以相互依賴。
在工程目錄下新建一個app.vue的文件并寫入以下內(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 語法提示:data () { } 等同于 data:function() { }
在<template>內(nèi)寫的HTML寫法完全同html文件,webpack最終會把它編譯為Render 函數(shù)的形式。寫在<style>里的樣式,我們已經(jīng)用插件 extract-text-webpack-plugin 配置過了,最終會統(tǒng)一提取并打包在main.css 里,因?yàn)榧恿藄cope 屬性,這部分樣式只會對當(dāng)前組件app.vue 有效。
.vue 的組件是沒有名稱的,在父組件使用時可以對它自定義。寫好了組件,就可以在入口main.js 中使用它了。打開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,第一個Vue 工程就跑起來了。
打開chrome調(diào)試工具,在elements 面板可以看到,<div id="app"> 已經(jīng)被組件替換成了:
<div data-v-381730fa> Hello Vue.js </div>
// 對應(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 慢的問題
可用 get命令查看registry
npm congfig get registry
原版結(jié)果為
http://registry.npmjs.org
用set命令換成阿里的鏡像就可以了
npm config set registry https://registry.npm.taobao.org
在執(zhí)行命令
npm install
接下來,在demo目錄下,再新建兩個文件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>
改寫根實(shí)例 app.vue 組件,把title.vue 和 button.vue 導(dǎo)入進(jìn)來:
<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)入的組件都是局部注冊的,而且可以自定義名稱,其他用法和組件一致。后面會基于webpack和單文件組件展開。
ES 6 語法提示:
=> 是箭頭函數(shù)
render: h=> h(App) 等同于:
render : function (h) {
return h (App)
}components: {
vTitle,
vButton
}
等同于:
components:{
vTitle : vTitle,
vButton : vButton
}
對象字面量縮寫,當(dāng)對象的key 和 value 名稱一致時,可以縮寫成一個。
14.用于生產(chǎn)環(huán)境。我們先對webpack 進(jìn)一步配置,來支持更多常用的功能。安裝url-loader 和 file-loader 來支持圖片、字體等文件:
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 等格式文件時,url-loader會把它們一起編譯到dist 目錄下," ?limit=1024" 是指如果這個文件小余1kb,就以base64的形式加載,不會生成一個文件。
找一張圖片,保存為 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
在安裝包時, 我們可以根據(jù)環(huán)境決定包的安裝效果. 假設(shè)我們要安裝express
1.執(zhí)行 npm i express --save則表示我想在生產(chǎn)環(huán)境中使用express, 同時, express的版本信息會被寫入package.json中的dependencies屬性中.
2.而執(zhí)行npm i express --save-dev 表示我想在開發(fā)和測試環(huán)境中使用. express的版本信息會被寫入package.json中的devDependencies屬性中.
3 --save可以簡寫為-S, --save-dev可以簡寫為-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)
三個命令:
1.查看npm服務(wù)器上所有的包版本信息
npm view babel-loader versions
2.查看該包最新的版本是哪一個
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.介紹打包上線前,先來分析webpack打包后的產(chǎn)物有哪些。
本書所介紹和使用的都是單頁面富應(yīng)用(SPA)技術(shù),這意味著最終只有一個html的文件,其余都是靜態(tài)資源。實(shí)際部署到生產(chǎn)環(huán)境時,一般會將html 掛在后端程序下,由后端路由渲染這個頁面,將頁面所有的靜態(tài)資源(css、js、image、icon、font等)單獨(dú)部署到CDN,當(dāng)然也可以和后端程序部署在一起,這樣就實(shí)現(xiàn)了前后端完全分離。
我們在webpack的output 選項(xiàng)里已經(jīng)指定了path 和 publicPath,打完包后,所有的資源都會保存在 demo/dist 目錄下。
打包會用到下面兩個依賴,使用NPM安裝:
npm install --save-dev webpack-merge
npm install --save-dev html-webpack-plugin
為了方便開發(fā)和生產(chǎn)環(huán)境的切換,我們在demo目錄下再新建一個用于生產(chǎn)環(huán)境的配置文件 webpack.prod.config.js。
編譯打包,直接執(zhí)行webpack 命令就可以。在package.json中,再加入一個build的快捷腳本用來打包:
"scripts" : {
"dev" : "webpack-dev-server --open --config webpack.config.js",
"build" : "webpack --progress --hide-modules --config webpack.prod.config.js"
}
先來看一下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 模塊就是用于合并兩個webpack 的配置文件,所以prod 的配置是在webpack.config.js 基礎(chǔ)上擴(kuò)展的。靜態(tài)資源在大部分場景下都有緩存(304),更新上線后一般都希望用戶能及時地看到內(nèi)容,所以給打包后的css和js文件的名稱都加了20位的hash值。這樣文件名就唯一了(比如 main.b3dd20e2dae9d76af86b.js),只要不對html文件設(shè)置緩存,上線后立即就可以加載最新的靜態(tài)資源。
html-webpack-plugin 是用來生成html 文件的,它通過template 選項(xiàng)來讀取指定的模板 index.ejs,然后輸出到filename 指定的目錄,也就是demo/index_prod.html。模板 index.ejs 動態(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,等待一會就會完成打包,成功后在demo下會生成一個dist的目錄,里面就是打包完的所有靜態(tài)資源。
ejs 是一個JavaScript 模板庫,用來從JSON 數(shù)據(jù)中生成HTML 字符串,常用于 Node.js。
webpack除了上述內(nèi)容外,和有很多高級的配置和豐富的插件及加載器,可查閱webpack文檔:https://webpack.js.org/
本章代碼:https://github.com/icarusion/vue-book
vue-book 下的demo目錄下執(zhí)行 npm install 命令會自動安裝所有的依賴,然后執(zhí)行 npm run dev 啟動服務(wù)。