1、Webpack 是什麼?php
webpack是一款模塊加載器兼打包工具,它能把各類資源,例如JS(含JSX)、coffee、樣式(含less/sass)、圖片等都做爲模塊來使用和處理。 簡單說就是模塊加載器,經過使用Webpack,可以像Node.js同樣處理依賴關係,而後解析出模塊之間的依賴,將代碼打包。css
像sass,JSX等代碼雖然極大的提升了開發效率,可是自己並不被瀏覽器所識別,須要咱們對其進行編譯和打包,變成瀏覽器識別的代碼html
模塊化(讓咱們能夠把複雜的代碼細化爲小的文件)前端
優化加載速度(壓縮和合並代碼來提升加載速度,壓縮能夠減小文件體積,代碼合併能夠減小http請求)node
使用新的開發模式react
同時支持CommonJS和AMD模塊(對於新項目,推薦直接使用CommonJS);jquery
串聯式模塊加載器以及插件機制,讓其具備更好的靈活性和擴展性,例如提供對CoffeeScript、ES6的支持;webpack
能夠基於配置或者智能分析打包成多個文件,實現公共模塊或者按需加載;web
支持對CSS,圖片等資源進行打包,從而無需藉助Grunt或Gulp(browserify只能打包JS文件);正則表達式
開發時在內存中完成打包,性能更快,徹底能夠支持開發過程的實時打包需求;
對source map有很好的支持。
var webpack = require('webpack');
var path = require('path');
var SpritesmithPlugin = require('webpack-spritesmith');
module.exports = {
// context: __dirname + '\\app', //上下文
entry: path.resolve(__dirname, 'app/index.js'), //入口文件
output: { //輸出文件
path: path.resolve(__dirname, 'app/build/script'),
filename: 'bundle.js'
},
module: {
loaders: [ //加載器
{test: /\.html$/, loader: 'raw'},
// {test: /\.css$/, loader: 'style!css!postcss'},
{test: /\.css$/, loader: 'style!css'},
// {test: /\.(png|jpg|ttf)$/, loader: 'url?limit=8192'}
{test: /\.(png|jpg|ttf)$/, loader: 'file!url?limit=8192'}
]
},
// postcss: function () {
// return [autoprefixer];
// },
plugins: [ //插件
new webpack.BannerPlugin('This file is created by shiddong.'),
new SpritesmithPlugin({
src: {
cwd: path.resolve(__dirname, 'app/images/'),
glob: '*.png'
},
target: {
image: path.resolve(__dirname, 'app/build/images/sprite.png'),
css: path.resolve(__dirname, 'app/build/css/sprite.css') //產生的樣式文件,圖片的樣式類名是 icon-圖片名
},
apiOptions: {
cssImageRef: '../images/sprite.png'
},
spritesmithOptions: {
algorithm: 'top-down'
}
})
]
};
入口文件,能夠傳字符串,那說明入口文件只有一個;也能夠傳數組或對象,指定多個入口文件。
有兩種語法:
<1> 先require path,再利用reslove方法對路徑進行解析。
var path = require('path');
entry: path.resolve(__dirname, 'app/index.js'), //入口文件
<2> 先定義好上下文路徑,那麼entry中的路徑直接在這個路徑下開始
context: __dirname + '\\app', //上下文
entry: './index.js', //入口文件
注:webpack中引入的path是nodejs內置的package,用來處理路徑 —— 參考菜鳥教程node.js工具模塊。
當entry是數組的時候,裏面一樣包含入口js文件,另一個參數能夠是用來配置webpack提供的一個靜態資源服務器,webpack-dev-server。webpack-dev-server會監控項目中每個文件的變化,實時的進行構建,而且自動刷新頁面:
entry: [
'webpack/hot/only-dev-server',
'./js/app.js'
]
當entry是個對象的時候,咱們能夠將不一樣的文件構建成不一樣的文件,按需使用。每個鍵值對,就是一個入口文件。
備註:固然也有其餘的辦法,如express框架,在index.html同路徑創建一個server.js,而後運行 node server.js便可。
// express 是一個基於Node.js 平臺的web應用開發框架 —— 快速、極簡、開放
var port = 8000,
express = require('express'),
app = express();
app.use('/', express.static(__dirname));
app.listen(port);
console.log('Now serving http://localhost:' + port + '/index.html');
生成打包文件的配置,能夠指定path(路徑),當有多個入口文件時,還可使用[name]、[hash]、[chunkhash]等值,來對應替換爲入口的文件的配置。
output: { //輸出構建後的文件
path: path.resolve(__dirname, 'app/build/script'),
filename: 'bundle.js'
}
當entry中定義構建多個文件時,filename能夠對應的更改成[name].js用於定義不一樣文件構建後的名字。
entry: {
index: 'index.js'
},
output: {
path: './js',
filename: '[name].bundle.js' // [name] 會由entry中的鍵(這裏是index)替換
}
定義了對模塊的處理邏輯,在webpack中,全部的資源都被當作模塊。對於不一樣文件類型的資源,都有對應的loader。
模塊的加載相關配置定義在module.loaders中。
loaders: 加載器配置,經過正則表達式去匹配不一樣後綴的文件名,而後給它們定義不一樣的加載器。它能夠轉換項目中的資源文件,好比說給css文件定義串聯的兩個加載器(!用來定義級聯關係),順序是從右向左使用:
module: {
loaders: [
{ test: /\.js?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
{ test: /\.css$/, loader: "style!css" },
{ test: /\.less/, loader: 'style-loader!css-loader!less-loader'}
]
}
其中,exclude: /node_modules/,
exclude,include手動添加屏蔽不須要處理的文件(文件夾)或必須處理的文件(文件夾)
比較經常使用的loader:
css-loader: 將樣式打包成字符串。
style-loader:將樣式字符串添加到頁面的style標籤中
還能夠添加用來定義png、jpg這樣的圖片資源在大於8k時正常打包,小於8k時自動處理爲base64圖片的加載器:
{ test: /\.(png|jpg)$/,loader: 'url-loader?limit=8192'}
其中,? 表示加載器支持經過查詢字符串的方式接受參數。
給css和less還有圖片添加了loader以後,咱們不只能夠像在node中那樣require js文件了,咱們還能夠require css、less甚至圖片文件:
require('./bootstrap.css');
require('./myapp.less');
var img = document.createElement('img');
img.src = require('./glyph.png');
這樣require來的文件會內聯到 js bundle中。若是咱們須要保留require的寫法又想把css文件單獨拿出來,可使用[extract-text-webpack-plugin]插件。
插件,它能夠幹不少不少的事情,很是強大,官方提供了不少插件,第三方也能夠寫插件。對於用到的插件,只須要將插件new出來放到數組中便可。
<1> BannerPlugin 內置插件來實踐插件的配置和運行,這個插件的做用是給輸出的文件頭部添加註釋信息。
<2> ProvidePlugin 插件的做用是自動加載jquery模塊,也就是說將jquery變成了全局的模塊,固然咱們須要在index.html中使用script標籤導入。
[緣由:因爲jquery沒有模塊化的概念,也沒有適配webpack,因此咱們使用jquery時,須要在index.html中導入,而後使用 ProvidePlugin 插件使其自動加載。]
plugins: [
new webpack.BannerPlugin('This file is created by shiddong.'),
// 此插件會自動加載jquery,解決jquery沒法引用的問題
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
window.jQuery: "jquery"
})
]
只須要在index.html中導入bundle.js,<script src="bundle.js">script>,不須要在index.html中導入js文件了,只須要使用 require 導入模塊就行,webpack會本身解決它們之間的依賴。
<1> 依賴第三方庫能夠將其下載到node-modules中,而後導入相應的模塊:
//require('angular')導入的是 node_modules 中的angular模塊
require("angular"); //var angular = require('angular');
require("bootstrap");
var demoApp = angular.module('demoApp', []);
<2> 或者相似於導入本地的js文件,能夠創建一個 common.js 文件,而後導入 angular 和 bootstrap。而後在使用的時候直接require('./common')
loaders: [
{
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=8192'
}
]
其中,
<1> test 屬性表明能夠匹配的圖片類型,除了 png、jpg 以外也能夠添加 gif 等,以豎線隔開即開。
<2> loader 後面 limit 字段表明圖片打包限制,這個限制並非說超過了就不能打包,而是指當圖片大小小於限制時會自動轉成 base64 碼引用。上例中大於8192字節的圖片正常打包,小於8192字節的圖片以 base64 的方式引用。
//Option 1,使用 ?
{ test: /\.png$/,
loader: 'url-loader?limit=1024'
}
//Option 2,使用query屬性
{ test: /\.png$/,
loader: 'url-loader',
query: {limit=1024}
}
<3> url-loader 後面除了 limit 字段,還能夠經過 name 字段來指定圖片打包的目錄與文件名:
loaders: [
{
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
}
]
name 字段指定了在打包根目錄(output.path)下生成名爲 images 的文件夾,並在原圖片名前加上8位 hash 值。
var path = require('path');
var SpritesmithPlugin = require('webpack-spritesmith'); //安裝雪碧圖依賴模塊:webpack-spritesmith
module.exports = {
entry: path.resolve(__dirname, 'app/main.js'),
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js'
},
plugins: [
new SpritesmithPlugin({
src: {
cwd: path.resolve(__dirname, 'app/images/'),
glob: '*.png'
},
target: {
image: path.resolve(__dirname, 'build/images/sprite.png'),
css: path.resolve(__dirname, 'build/css/sprite.css') //產生的樣式文件,圖片的樣式類名是 icon-圖片名
},
apiOptions: {
cssImageRef: '../images/sprite.png'
},
spritesmithOptions: {
algorithm: 'top-down'
}
})
]
};
連接:https://zhuanlan.zhihu.com/p/23873229
其餘:
定義解析模塊路徑時的配置,最經常使用的就是extensions,能夠用來指定模塊的後綴,這樣在引入模塊是就不須要寫後綴了,會自動補全。
webpack在構建包的時候會按目錄的進行文件的查找,resolve屬性中的extensions數組中用於配置程序能夠自行補全哪些文件後綴:
resolve:{
extensions:['', '.js', '.json']
}
而後咱們想要加載一個js文件時,只要require('common')就能夠加載common.js文件了。
當咱們想在項目中require一些其餘的類庫或者API,而又不想讓這些類庫的源碼被構建到運行時文件中,這在實際開發中頗有必要。此時咱們就能夠經過配置externals參數來解決這個問題:
externals: {
"jquery": "jQuery"
}
這樣咱們就能夠放心的在項目中使用這些API了:var jQuery = require(「jquery」);
當咱們在require一個模塊的時候,若是在require中包含變量,像這樣:
require("./mods/" + name + ".js");
那麼在編譯的時候咱們是不能知道具體的模塊的。但這個時候,webpack也會爲咱們作些分析工做:
1.分析目錄:'./mods';
2.提取正則表達式:'/^.*.js$/';
因而這個時候爲了更好地配合webpack進行編譯,咱們能夠給它指明路徑,像在cake-webpack-config中所作的那樣(咱們在這裏先忽略abcoption的做用):
var currentBase = process.cwd();
var context = abcOptions.options.context ? abcOptions.options.context :
path.isAbsolute(entryDir) ? entryDir : path.join(currentBase, entryDir);
傳統的模塊打包工具(module bundlers)最終將全部的模塊編譯生成一個龐大的bundle.js文件。可是在真實的app裏邊,「bundle.js」文件可能有10M到15M之大可能會致使應用一直處於加載中狀態。所以Webpack使用許多特性來分割代碼而後生成多個「bundle」文件,並且異步加載部分代碼以實現按需加載。
若是經過npm install -g webpack方式安裝webpack的話,能夠經過命令行直接執行打包命令,好比:
$ webpack –config webpack.config.js
這樣就會讀取當前目錄下的webpack.config.js做爲配置文件執行打包操做。默認查找webpack.config.js,因此咱們在這裏只須要執行webpack 命令便可。
在開發環境構建一次
webpack
構建並生成源代碼映射文件
webpack -d
在生成環境構建,壓縮、混淆代碼,並移除無用代碼
webpack -p
快速增量構建,能夠和其餘選項一塊兒使用
webpack –watch
progress 顯示打包過程當中的進度,colors打包信息帶有顏色顯示
webpack –progress –colors
require(‘lodash’) // 從模塊目錄查找
require(‘./file’) // 按相對路徑查找
CSS 及圖片的引用
require(‘./bootstrap.css’);
require(‘./myapp.less’);
var img = document.createElement(‘img’);
img.src = require(‘./weibo.png’);
OccurenceOrderPlugin:給常用的模塊分配最小長度的id,這樣能夠減小文件大小。
HotModuleReplacementPlugin:是熱替換,熱替換和dev-server的hot有什麼區別?不用刷新頁面,可用於生產環境。
NoErrorsPlugin:在打包時不會由於錯誤而中斷
ProvidePlugin: 定義一些在import時能自動引入的變量,如定義了 $: 'jquery' 後,能夠在文件中直接使用$,webpack能夠自動幫你加上 var $ = require('jquery')。
DllPlugin: 將一些模塊預編譯,相似windows裏的dll,能夠在項目中直接使用,無需再構建。注意要在output中指定 library ,並在DllPlugin中指定與其一致的 name ,在有多個入口時可使用 [name] 和 [hash] 來區分,由於這個參數是要賦值到global上的,因此這裏使用 [hash] 不容易出現變量名衝突的狀況。
DllReferencePlugin: 引用以前打包好的dll文件,注意下context參數,這個應該根據manifest.json文件中的引用狀況來賦值,若是引用的都是npm安裝的庫,這裏就填項目根目錄就行了。
DefinePlugin: 能夠定義編譯時的全局變量,有不少庫(React, Vue等)會根據 NODE_ENV 這個變量來判斷當前環境。爲了儘量減小包大小,在生產環境中要定義其爲 JSON.stringify(「production」)
optimize.UglifyJsPlugin: 配置壓縮代碼。
optimize.DedupePlugin: 能夠減小重複文件數。
ExtractTextPlugin: 能夠將全部css文件打包到一個css文件中。
一、webpack參考連接
http://webpackdoc.com
二、Webpack入門(其文章底部有些連接能夠參考)———— 基本概念、webpack.config.js配置詳解
http://blog.csdn.net/liujie19901217/article/details/51026943
三、入門 Webpack,看這篇就夠了(很好,工做方式對比清晰、參數的表格清晰)******
http://www.javashuo.com/article/p-gqgzutje-er.html
四、[譯] 經過 Webpack 實現 AngularJS 的延遲加載 ******
https://toutiao.io/posts/46gvgm/preview
五、30分鐘手把手教你學webpack實戰(內容比較全面、詳細)******
http://www.cnblogs.com/tugenhua0707/p/4793265.html
六、Webpack + Angular的組件化實踐
http://www.javashuo.com/article/p-fyfkahwh-hc.html
七、爲什麼webpack風靡全球?三大主流模塊打包工具對比
http://www.techug.com/webpack-requirejs-browserify
webpack: code spliting / loader/plugin
八、前端構建工具漫談,fis三、webpack、rollup.js
https://zhuanlan.zhihu.com/p/20933749
九、輕鬆入門webpack——官方文檔解讀
http://shuaihua.cc/article/webpack/webpack.php
十、關於雪碧圖的詳細介紹
https://zhuanlan.zhihu.com/p/23873229?utm_source=tuicool&utm_medium=referral
十一、boi剖析 - 基於webpack的css sprites實現方案
http://www.cnblogs.com/ihardcoder/p/6053231.html