1. 程式人生 > >webpack快速入門和實戰

webpack快速入門和實戰

webpack是什麼

Webpack 是一個模組打包器。它將根據模組的依賴關係進行靜態分析,然後將這些模組按照指定的規則生成對應的靜態資源。

這張圖基本上解釋了webpack是用來幹嘛的,將一些相互依賴的模組(檔案),打包成一個或多個js檔案,減少http請求次數,提升效能。這些相互依賴的模組可以是圖片、字型、coffee檔案、樣式檔案、less檔案等。

1、 安裝

先安裝

install node.js
node.js包含一個包管理器:npm

基本命令

      webpack         // 最基本的啟動webpack的方法
      webpack -w
// 提供watch方法;實時進行打包更新 webpack -p // 對打包後的檔案進行壓縮 webpack -d // 提供source map,方便調式程式碼

全域性安裝

 # npm install webpack -g

專案安裝:

最好在工程中使用webpack,讓webpack作為工程的依賴。這樣你就能自己選擇一個本地的webpack版本,不會強制使用全域性的。

  # 進入專案目錄
  # 確定已經有 package.json,沒有就通過 npm init 建立
  # 安裝 webpack 依賴
  # npm install webpack --save-dev

2、如何使用

使用ES6

安裝 babel-loader: 
# npm install babel-loader --save-dev
安裝轉碼規則:       
# npm install babel-preset-es2015 --save-dev
ES7不同階段語法提案的轉碼規則(共有4個階段),選裝一個
# npm install --save-dev babel-preset-stage-0
# npm install --save-dev babel-preset-stage-1
# npm install --save-dev babel-preset-stage-2
# npm install --save-dev babel-preset-stage-3 參考格式: { test: /\.js$/, loader: 'babel?presets[]=es2015,presets[]=stage-0' }

編譯css

    安裝css-loader:  
    # npm install css-loader  --save-dev
    安裝style-loader  
    # npm install style-loader  --save-dev
    參考格式:
    {
        test: /\.css$/,
        loaders: ['style', 'css', 'autoprefixer']
    }

編譯less

    # npm install less --save-dev
    安裝less-loader: 
    # npm install less-loader --save-dev
    參考格式:
    {
        test: /\.less/,
        loaders: ['style', 'css', 'autoprefixer', 'less'],
    }

使用autoprefixer自動補上瀏覽器相容

    # npm install autoprefixer-loader --save-dev
    參考格式:
    {
        test: /\.css$/,
        loaders: ['style', 'css', 'autoprefixer']
    }, {
        test: /\.less/,
        loaders: ['style', 'css', 'autoprefixer', 'less'],
    }

編譯檔案

    安裝file-loader: 
    # npm install file-loader --save-dev
    參考格式:
    {
        test: /\.(eot|woff|svg|ttf|woff2|gif)(\?|$)/,
        loader: 'file-loader?name=[hash].[ext]'
    }

編譯圖片

    # npm install url-loader --save-dev
    參考格式:
    {
    test: /\.(png|jpg)$/,
    loader: 'url?limit=1200&name=[hash].[ext]'
    }

編譯JSX

    # npm install jsx-loader --save-dev
    # npm install babel-preset-react --save-dev
    參考格式:
    {
    test: /\.jsx$/,
    loaders: ['jsx', 'babel?presets[]=es2015,presets[]=stage-0,presets[]=react']
    }

示例原始碼

在專案目錄下,新建一個webpack.config.js檔案,把下面程式碼複製進去,然後在新建一個app.js和index.js檔案,寫上console.log(‘你好世界’);

執行命令:webpack 然後找到build目錄就看到編譯後的檔案了

    var webpack = require('webpack');

    module.exports = {
      entry: {
          app: './app', //編譯的入口檔案
          index: './index', //編譯的入口檔案
      },
      output: {
          publicPath: '/build/', //伺服器根路徑
          path: './build', //編譯到當前目錄
          filename: '[name].js' //編譯後的檔名字
      },
      module: {
          loaders: [{
                  test: /\.js$/,
                  loader: 'babel?presets=es2015'
              }, {
                  test: /\.css$/,
                  loaders: ['style', 'css', 'autoprefixer']
              }, {
                  test: /\.less/,
                  loaders: ['style', 'css', 'autoprefixer', 'less'],
              }, {
                  test: /\.(eot|woff|svg|ttf|woff2|gif)(\?|$)/,
                  loader: 'file-loader?name=[hash].[ext]'
              }, {
                  test: /\.(png|jpg)$/,
                  loader: 'url?limit=1200&name=[hash].[ext]' //注意後面那個limit的引數,當你圖片大小小於這個限制的時候,會自動啟用base64編碼圖片
              }
          ]
      },
      plugins: [
              new webpack.optimize.CommonsChunkPlugin('common.js') //將公用模組,打包進common.js
      ],
      resolve: {
          extensions: ['', '.js', '.jsx'] //字尾名自動補全
      }
    };

plugins:可以使用外掛講幾個公共模組載入到common.js中,這樣就就可以更好的維護程式碼,但是要注意的是:

3. 詳細講解

webpack.config.js檔案通常放在專案的根目錄中,它本身也是一個標準的Commonjs規範的模組。在匯出的配置物件中有幾個關鍵的引數:

1.entry

entry可以是個字串或陣列或者是物件。

當entry是個字串的時候,用來定義入口檔案:

     entry: './js/main.js'

當entry是個陣列的時候,裡面同樣包含入口js檔案,另外一個引數可以是用來配置webpack提供的一個靜態資源伺服器,webpack- dev-server。webpack-dev-server會監控專案中每一個檔案的變化,實時的進行構建,並且自動重新整理頁面:

     entry: [
         'webpack/hot/only-dev-server',
         './js/app.js'
     ]

當entry是個物件的時候,我們可以將不同的檔案構建成不同的檔案,按需使用,比如在我的hello頁面中只要``引入hello.js即可:

     entry: {
         hello: './js/hello.js',
         form: './js/form.js'
     }

2.output

output引數是個物件,用於定義構建後的檔案的輸出。其中包含path和filename:

     output: {
         path: './build',
         filename: 'bundle.js'
     }

當我們在entry中定義構建多個檔案時,filename可以對應的更改為[name].js用於定義不同檔案構建後的名字。

3.module

關於模組的載入相關,我們就定義在module.loaders中。這裡通過正則表示式去匹配不同字尾的檔名,然後給它們定義不同的載入器。比如說給less檔案定義串聯的三個載入器(!用來定義級聯關係):

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

此外,還可以新增用來定義png、jpg這樣的圖片資源在小於10k時自動處理為base64圖片的載入器:

    { test: /\.(png|jpg)$/,loader: 'url-loader?limit=10000'}

給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]外掛。

在 上面示例程式碼中配置的第一個loaders我們可以看到一個叫做react-hot的載入器。我的專案是用來學習react寫相關程式碼的,所以配置了一個 react-hot載入器,通過它,可以實現對react元件的熱替換。我們已經在entry引數中配置了webpack/hot/only-dev- server,所以我們只要在啟動webpack開發伺服器時開啟–hot引數,就可以使用react-hot-loader了。在 package.json檔案中這樣定義:

 "scripts": { 2 "start": "webpack-dev-server --hot --progress --colors", 3 "build": "webpack --progress --colors" 4 }

4.resolve

webpack在構建包的時候會按目錄的進行檔案的查詢,resolve屬性中的extensions陣列中用於配置程式可以自行補全哪些檔案字尾:

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

然後我們想要載入一個js檔案時,只要require('common')就可以載入common.js檔案了。
5.plugin

webpack提供了[豐富的元件]用來滿足不同的需求,當然我們也可以自行實現一個元件來滿足自己的需求。在我的專案裡面沒有特殊的需求,於是便只是配置了NoErrorsPlugin外掛,用來跳過編譯時出錯的程式碼並記錄,使編譯後執行時的包不會發生錯誤:

plugins: [
     new webpack.NoErrorsPlugin()
 ]

6.externals

當我們想在專案中require一些其他的類庫或者API,而又不想讓這些類庫的原始碼被構建到執行時檔案中,這在實際開發中很有必要。此時我們就可以通過配置externals引數來解決這個問題:

externals: {
 "jquery": "jQuery" 3 }

這樣我們就可以放心的在專案中使用這些API了:var jQuery = require("jquery");

7.context

當我們在require一個模組的時候,如果在require中包含變數,像這樣:

require("./mods/" + name + ".js");

那麼在編譯的時候我們是不能知道具體的模組的。但這個時候,webpack也會為我們做些分析工作:

1.分析目錄:'./mods'2.提取正則表示式:'/^.*\.js$/'

於是這個時候為了更好地配合wenpack進行編譯,我們可以給它指明路徑,像在cake-webpack-config中所做的那樣(我們在這裡先忽略abcoption的作用):

var currentBase = process.cwd();
var context = abcOptions.options.context ? abcOptions.options.context : 
path.isAbsolute(entryDir) ? entryDir : path.join(currentBase, entryDir);