webpack這個工具很是強大。對前端中全部模塊進行打包,輸出js文件,後續引入這個js文件,在服務器上線,而後在域名中訪問寫好的項目;webpack還能支持模塊化加載(相似python,import xxx from 'ooo')。中文官網連接地址:https://www.webpackjs.com/javascript
現今的不少網頁其實能夠看作是功能豐富的應用,它們擁有着複雜的JavaScript代碼和一大堆依賴包。爲了簡化開發的複雜度,前端社區涌現出了不少好的實踐方法。css
這些改進確實大大提升了開發效率,可是利用它們開發的文件每每須要進行額外的處理才能讓瀏覽器識別,手動處理很是繁瑣,WebPack類的工具的出現就是爲了解決這樣的需求。html
webpack 是一個現代 JavaScript 應用程序的 靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個 依賴關係圖(dependency graph),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成一個或多個 bundle。前端
WebPack能夠看作是模塊打包機:它作的事情是,分析你的項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),並將其轉換和打包爲合適的格式供瀏覽器使用。vue
Webpack和另外兩個並無太多的可比性,Gulp/Grunt是一種可以優化前端的開發流程的工具,而WebPack是一種模塊化的解決方案,不過Webpack的優勢使得Webpack在不少場景下能夠替代Gulp/Grunt類的工具。java
Grunt和Gulp的工做方式是:在一個配置文件中,指明對某些文件進行相似編譯,組合,壓縮等任務的具體步驟,工具以後能夠自動替你完成這些任務。node
Webpack的工做方式:把你的項目當作一個總體,經過一個給定的主文件(如:index.js),Webpack將從這個文件開始找到你的項目的全部依賴文件,使用loaders處理它們,最後打包爲一個(或多個)瀏覽器可識別的JavaScript文件。python
若是要將兩者進行比較,Webpack的處理速度更快更直接,能打包更多不一樣類型的文件。jquery
這個是解析咱們es6的代碼的,爲何要用它呢,由於對於一些ie瀏覽器,甚至FF瀏覽器,低版本的還不能識別咱們的es6代碼,那麼vue裏面好多還讓咱們去寫es6的代碼,這個時候咱們就能夠用babel這個工具將咱們的es6的代碼轉譯成瀏覽器能識別的代碼.webpack
左邊是咱們寫的es6代碼,右邊是經過babel這個工具編譯以後的代碼。這個代碼能在咱們各個瀏覽器中去識別。
因此babel是用於編寫下一代JavaScript的編譯器。
在前端中一個js文件就是一個模塊,在js中沒有模塊化的概念。
webpack:對前端中的資源編譯打包、支持模塊化es6的Model。
在webpack中,全部類型的文件均可以是模塊,包括Javascript、CSS、圖片、JSON。經過加載器(Loader)將JavaScript 的模塊推廣到其餘類型文件。
(1)2009年初,commonjs規範還未出來,此時前端開發人員編寫的代碼都是非模塊化的,
那個時候開發人員常常須要十分留意文件加載順序所帶來的依賴問題
(2)與此同時 nodejs 開啓了js全棧大門,而 requirejs 在國外也帶動着前端逐步實現模塊化
同時國內 seajs(海納百川 有容乃大)也進行了大力推廣
AMD 規範 ,具體實現是:requirejs define('模塊id',[模塊依賴1,模塊依賴2],function(){ return ;}) , ajax請求文件並加載
Commonjs || CMD 規範seajs 淘寶玉伯
commonjs和cmd很是類似的
cmd require/module.exports
commonjs是js在後端語言的規範: 模塊、文件操做、操做系統底層
CMD 僅僅是模塊定義
UMD 通用模塊定義,一種既能兼容amd也能兼容commonjs 也能兼容瀏覽器環境運行的萬能代碼
(3)npm/bower集中包管理的方式備受青睞,12年browserify/webpack誕生
npm 是能夠下載先後端的js代碼475000個包
bower 只能下載前端的js代碼,bower 在下載bootstrap的時候會自動的下載jquery
browserify 解決讓require能夠運行在瀏覽器,分析require的關係,組裝代碼
webpack 打包工具,佔市場主流
(4)es6的module
export default {} || fn || msg,前端中也是有模塊的,導入方式是下面這種用法。
import xxx from './index.js'
es6Module 支持import(導入)和export(導出)。跟python的import很像。但它必須在服務器環境下才支持,或者咱們可能經過webpack的babel-loader將es6支持轉化成es6的語言。
# 下載webpack,-g表明全局 $ npm i webpack@3.12.0 -g # 查看webpack $ webpack -v 3.12.0
在webpack-demo 目錄中新建index.html文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模塊的基本使用</title> </head> <body> <!--<script type="text/javascript" src="App.js"></script>--> <!--<script type="text/javascript" src="main.js"></script>--> <script type="text/javascript" src="bundle.js"></script> </body> </html>
建立App.js文件:
// es6 module export拋出 import導入 let obj = { name: 'alex' }; export default obj; let age = 23; export {age}; // 做爲一個key拋出 export var fav = "雞湯"; export function add() { console.log('彈出了') }
建立main.js文件:
import app from './App.js' console.log(app); import {age, fav, add} from './App.js' console.log(age); console.log(fav); add();
使用webpack將main.js 打包成 bundle.js文件:
$ webpack ./main.js ./bundle.js Hash: 9f8da91e23bd4d667df5 Version: webpack 3.12.0 Time: 96ms Asset Size Chunks Chunk Names bundle.js 3.54 kB 0 [emitted] main [0] ./App.js 186 bytes {0} [built] [1] ./main.js 128 bytes {0} [built]
查看瀏覽器conosle輸出:
將main.js的內容作以下簡寫:
import * as o from './App.js' console.log(o);
再次將index.js進行打包:
$ webpack ./main.js ./bundle.js
查看頁面輸出,做爲整個對象拋出,以下所示:
建立index.html內容以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模塊的基本使用</title> </head> <body> <div id="app"></div> <script type="text/javascript" src="bundle.js"></script> </body> </html>
建立App.js內容以下:
// es6 module export拋出 import導入 let App = { template: ` <div> 我是一個App組件 </div> ` }; export default App; let age = 23; export {age}; // 做爲一個key拋出 export var fav = "雞湯"; export function add() { console.log('彈出了') }
建立main.js內容以下,引入vue.js文件:
import * as o from './App.js' console.log(o); import Vue from './vue.js' // 引入Vue模塊 new Vue({ el: '#app', data(){ return { } }, template:` <App/> `, components: { App:o.default } })
執行webpack,將main.js 打包成 bundle.js文件:
$ webpack ./main.js ./bundle.js Hash: b8b29cf57e405a8f2ee4 Version: webpack 3.12.0 Time: 645ms Asset Size Chunks Chunk Names bundle.js 309 kB 0 [emitted] [big] main [0] (webpack)/buildin/global.js 509 bytes {0} [built] [1] ./main.js 396 bytes {0} [built] [2] ./App.js 257 bytes {0} [built] [3] ./vue.js 289 kB {0} [built]
顯示效果以下所示:
webpack.config.js這個配置文件文件名是webpack默認的配置文件文件名。
首先進入項目目錄webpack_demo(最近父目錄不能是中文)並完成初始化項目:
$ npm init --yes
項目初始化完成後,目錄中多出package.json文件,內容以下所示:
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
在webpack_demo項目根目錄中安裝 webpack:
$ npm i webpack@3.12.0 -D
上例中指定了 webpack 版本號,若是下載時沒有指定,安裝完成後能夠看到當前安裝的webpack版本號。
因爲配置插件越多命令行會越長(webpack ./main.js ./bundle.js),此時,能夠將命令行參數移入webpack配置文件。
新建一個 webpack.config.js 文件:
module.exports = { // entry入口 entry: { main: './main.js' }, // output出口 output: { filename: './bundle.js' } }
index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模塊的基本使用</title> </head> <body> <div id="app"></div> <!--<script type="text/javascript" src="App.js"></script>--> <!--<script type="text/javascript" src="main.js"></script>--> <script type="text/javascript" src="bundle.js"></script> </body> </html>
javascript文件:
// App.js let App = { template: ` <div> 我是一個App組件 </div> ` }; export default App; let age = 23; export {age}; // 做爲一個key拋出 export var fav = "雞湯"; export function add() { console.log('彈出了') } // main.js import * as o from './App.js' console.log(o); import Vue from './vue.js' // 引入Vue模塊 new Vue({ el: '#app', data(){ return { } }, template:` <App/> `, components: { App:o.default } })
$ webpack
執行打包後,查看頁面顯示效果:
因爲在平常使用中,經常分有開發環境和生成環境。在生產環境下但願配置有watch,可以去自動編譯。但在開發環境下,則不須要有watch,打包完成後退出便可。
在這裏複製兩份webpack.config.js文件分別命名爲:webpack.dev.config.js、webpack.prod.config.js。
而後須要配置package.json文件,讓它可以識別這兩個新的js文件:
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "webpack --config ./webpack.dev.config.js", "build": "webpack --config ./webpack.prod.config.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^3.12.0" } }
執行npm run dev/build 來分別給生產環境和開發環境打包:
$ npm run dev $ npm run build
在上面的webpack_demo項目中沒有添加css樣式。若是要添加css樣式,一個是能夠直接寫在標籤的 style 屬性中。
再就是能夠寫在css文件中,在目錄中新增main.css文件:
body{ background-color: red; }
而後在main.js中引入應用:
import * as o from './App.js' import Vue from './vue.js' // 引入Vue模塊 // 導入css import './main.css' new Vue({ el: '#app', data(){ return { } }, template:` <App/> `, components: { App:o.default } })
此時執行npm run dev,就會發現報錯以下所示:
Version: webpack 3.12.0 Time: 670ms Asset Size Chunks Chunk Names ./bundle.js 309 kB 0 [emitted] [big] main [0] (webpack)/buildin/global.js 509 bytes {0} [built] [1] ./main.js 409 bytes {0} [built] [2] ./App.js 257 bytes {0} [built] [3] ./vue.js 289 kB {0} [built] [7] ./main.css 169 bytes {0} [built] [failed] [1 error] + 3 hidden modules ERROR in ./main.css Module parse failed: Unexpected token (1:4) You may need an appropriate loader to handle this file type. | body{ | background-color: red; | } @ ./main.js 12:0-19
style
標籤須要注意的是:若是隻使用了 css-loader,則 webpack 只是將CSS文件預處理成模塊而後打包到構建文件中,並不會插入到頁面(這是 style-loader 的做用)。
$ npm install css-loader -D;
$ npm install style-loader -D
下載完成後,能夠看到package.json中多了這兩個組件:
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "webpack --config ./webpack.dev.config.js", "build": "webpack --config ./webpack.prod.config.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "css-loader": "^2.1.1", "style-loader": "^0.23.1", "webpack": "^3.12.0" } }
修改配置讓webpack識別這兩個loader :
module.exports = { // entry入口 entry: { main: './main.js' }, // output出口 output: { filename: './bundle.js' }, watch:true, // 模塊中的loader,loader加載器能對css、json、png、jpg、mp三、mp四、es6的js代碼解析 module:{ loaders:[ { test:/\.css$/, // css結尾的 loader:'style-loader!css-loader' // 依次識別 } ] } }
須要注意的是,loader的順序很是重要,加載器的執行順序是從後往前的,若是把 sytle-loader 放在 css-loader 後面,style-loader 是沒法理解CSS文件的,須要先通過 css-loader 預處理。
在完成項目開發後,將輸出文件打包:
$ npm run dev > webpack_demo@1.0.0 dev /Users/.../webpack_demo > webpack --config ./webpack.dev.config.js Hash: 45b4436bff4c76fd3bc8 Version: webpack 3.12.0 Time: 1142ms Asset Size Chunks Chunk Names ./bundle.js 326 kB 0 [emitted] [big] main [0] (webpack)/buildin/global.js 509 bytes {0} [built] [1] ./main.js 409 bytes {0} [built] [2] ./App.js 257 bytes {0} [built] [3] ./vue.js 289 kB {0} [built] [7] ./main.css 1.07 kB {0} [built] [8] ./node_modules/css-loader/dist/cjs.js!./main.css 1
顯示效果:
該插件將爲您生成一個HTML5文件,其中包含使用script
標記在正文中的全部webpack包。
(1)該插件主要有兩個主要做用:
(2)插件生成html文件的原理:
將 webpack中 entry 配置的相關入口 chunk 和 extract-text-webpack-plugin 抽取的css樣式 插入到該插件提供的 template 或者 templateContent 配置項指定的內容基礎上生成一個html文件,具體插入方式是將樣式 link 插入到 head 元素中,script 插入到 head 或者 body 中。
建立src目錄後,建立編輯以下文件:
App.js文件:
// es6 module export拋出 import導入 var App = { template: `<div>{{msg}}</div>`, data(){ return { msg: "咱們學習module 哈哈哈哈 更改了數據" } } }; // 先拋出 export default App;
main.js文件:
import Vue from './vue.js' // 引入Vue模塊 import App from './App.js' // 導入css import './main.css' new Vue({ el: '#app', data(){ return { } }, template:` <App/> `, components: { App } })
main.css文件:
body{ background-color: red; }
還在src引入vue.js文件:
npm install vue -S
在根目錄中構建各類配置文件:package.json、wabpack.conf.js、wabpack.dev.conf.js、wabpack.prod.conf.js。
在根目錄中構建index.html模板文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模塊的基本使用</title> </head> <body> <div id="app"></div> </body> </html>
在根目錄建立dist目錄。distdistsd
$ npm install html-webpack-plugin -D
調整webpack.config.js配置文件,將插件添加到webpack配置中:
// node.js中內容模塊 var path = require('path'); var HtmlWebpackPlugin = require('html-webpack-plugin'); // html-webpack-plugin module.exports = { // entry入口 entry: { main: './src/main.js' }, // output出口 output: { path:path.resolve('./dist'), // 相對轉絕對 filename: './bundle.js' }, watch:true, // 模塊中的loader module:{ loaders:[ { test:/\.css$/, // css結尾的 loader:'style-loader!css-loader' // 依次識別 } ] }, // 插件 plugins:[ new HtmlWebpackPlugin({ template: './index.html', // 參照模板,以這個文件爲參照物生成到dist目錄 }) ] }
注意做爲模板參照的index.html裏去除以前bundle.js的引入。
執行npm run dev/build 來分別給生產環境和開發環境打包
$ npm run build
執行完成後,能夠看到dist目錄下多出了兩個文件:bundle.js 和 index.html。具體index.html內容以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模塊的基本使用</title> </head> <body> <div id="app"></div> <script type="text/javascript" src="./bundle.js"></script></body> </html>
顯示效果以下所示:
安裝http-server(必需要有node和npm):
$ npm install -g http-server
啓動服務:
找到你的文件夾,在當前文件夾下打開命令行,輸入http-server,默認啓動是8080端口。
$ hs -o -p 8890
自動打開瀏覽器顯示效果以下所示:
webpack 提供 webpack-dev-server 來解決自動刷新瀏覽器的問題。它是一個基於 expressjs的開發服務器,提供實時刷新瀏覽器頁面的功能。
在項目下安裝 webpack-dev-server:
$ npm install webpack-dev-server -D
下載完成後package.json中出現對應信息:
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "webpack --config ./webpack.dev.config.js", "build": "webpack --config ./webpack.prod.config.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "css-loader": "^2.1.1", "html-webpack-plugin": "^3.2.0", "style-loader": "^0.23.1", "webpack": "^3.12.0", "webpack-dev-server": "^3.3.1" } }
在這個版本下,運行 npm run dev 須要有 webpack-cli。老版本則不須要:
$ npm install webpack-dev-server@2.9.0 -D
執行後修改 package.json內容以下所示:
"devDependencies": { "css-loader": "^2.1.1", "html-webpack-plugin": "^3.2.0", "style-loader": "^0.23.1", "webpack": "^3.12.0", "webpack-dev-server": "^2.9.0" } }
--hot:熱承載,頁面數據修改自動刷新
--open:自動打開網頁
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "webpack-dev-server --open --hot --inline --config ./webpack.dev.config.js", "build": "webpack --config ./webpack.prod.config.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "css-loader": "^2.1.1", "html-webpack-plugin": "^3.2.0", "style-loader": "^0.23.1", "webpack": "^3.12.0", "webpack-dev-server": "^2.9.0" } }
此時執行以下命令,會自動在瀏覽器打開 http://localhost:8080頁面
$ npm run dev
修改App.js中內容保存後,頁面顯示自動刷新。