webpack總結

1、Webpack 是什麼?php

webpack是一款模塊加載器兼打包工具,它能把各類資源,例如JS(含JSX)、coffee、樣式(含less/sass)、圖片等都做爲模塊來使用和處理。 簡單說就是模塊加載器,經過使用Webpack,可以像Node.js同樣處理依賴關係,而後解析出模塊之間的依賴,將代碼打包。css

2、爲何須要打包?

  • 像sass,JSX等代碼雖然極大的提升了開發效率,可是自己並不被瀏覽器所識別,須要咱們對其進行編譯和打包,變成瀏覽器識別的代碼html

  • 模塊化(讓咱們能夠把複雜的代碼細化爲小的文件)前端

  • 優化加載速度(壓縮和合並代碼來提升加載速度,壓縮能夠減小文件體積,代碼合併能夠減小http請求)node

  • 使用新的開發模式react

3、webpack主要特性

  • 同時支持CommonJS和AMD模塊(對於新項目,推薦直接使用CommonJS);jquery

  • 串聯式模塊加載器以及插件機制,讓其具備更好的靈活性和擴展性,例如提供對CoffeeScript、ES6的支持;webpack

  • 能夠基於配置或者智能分析打包成多個文件,實現公共模塊或者按需加載;web

  • 支持對CSS,圖片等資源進行打包,從而無需藉助Grunt或Gulp(browserify只能打包JS文件);正則表達式

  • 開發時在內存中完成打包,性能更快,徹底能夠支持開發過程的實時打包需求;

  • source map有很好的支持。

4、配置(webpack.config.js文件)

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'
           }
       })
    ]
};

 

5、webpack.config.js 配置詳解

(1)entry

入口文件,能夠傳字符串,那說明入口文件只有一個;也能夠傳數組或對象,指定多個入口文件。

有兩種語法:

<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');

(2)output

生成打包文件的配置,能夠指定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)替換
}

(3)module

定義了對模塊的處理邏輯,在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]插件。

(4)plugins

插件,它能夠幹不少不少的事情,很是強大,官方提供了不少插件,第三方也能夠寫插件。對於用到的插件,只須要將插件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"
    })
]

(5)導入使用

只須要在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')

(6)處理圖片

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 值。

(7)生成雪碧圖

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


其餘:

(8)resolve

定義解析模塊路徑時的配置,最經常使用的就是extensions,能夠用來指定模塊的後綴,這樣在引入模塊是就不須要寫後綴了,會自動補全。
webpack在構建包的時候會按目錄的進行文件的查找,resolve屬性中的extensions數組中用於配置程序能夠自行補全哪些文件後綴:

resolve:{
    extensions:['', '.js', '.json']
}

而後咱們想要加載一個js文件時,只要require('common')就能夠加載common.js文件了。

(9)externals

當咱們想在項目中require一些其餘的類庫或者API,而又不想讓這些類庫的源碼被構建到運行時文件中,這在實際開發中頗有必要。此時咱們就能夠經過配置externals參數來解決這個問題:

externals: {
    "jquery": "jQuery"
}

這樣咱們就能夠放心的在項目中使用這些API了:var jQuery = require(「jquery」);

(10)context

當咱們在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);

 

6、按需加載

傳統的模塊打包工具(module bundlers)最終將全部的模塊編譯生成一個龐大的bundle.js文件。可是在真實的app裏邊,「bundle.js」文件可能有10M到15M之大可能會致使應用一直處於加載中狀態。所以Webpack使用許多特性來分割代碼而後生成多個「bundle」文件,並且異步加載部分代碼以實現按需加載。

7、執行打包

若是經過npm install -g webpack方式安裝webpack的話,能夠經過命令行直接執行打包命令,好比:
$ webpack –config webpack.config.js
這樣就會讀取當前目錄下的webpack.config.js做爲配置文件執行打包操做。默認查找webpack.config.js,因此咱們在這裏只須要執行webpack 命令便可。

8、經常使用webpack命令

在開發環境構建一次
webpack
構建並生成源代碼映射文件
webpack -d
在生成環境構建,壓縮、混淆代碼,並移除無用代碼
webpack -p
快速增量構建,能夠和其餘選項一塊兒使用
webpack –watch
progress 顯示打包過程當中的進度,colors打包信息帶有顏色顯示
webpack –progress –colors

9、理解文件路徑

require(‘lodash’) // 從模塊目錄查找
require(‘./file’) // 按相對路徑查找
CSS 及圖片的引用
require(‘./bootstrap.css’);
require(‘./myapp.less’);
var img = document.createElement(‘img’);
img.src = require(‘./weibo.png’);

10、其餘插件功能

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文件中。

 

11、參考資料

一、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

相關文章
相關標籤/搜索