webpack

官網
中文文檔
中文文檔
webpack是目前前端工程化實踐中最常用的打包工具,學習webpack,有利于我們掌握前端模塊化編程,也是我們在學習React,Vue等框架時做為重要支撐。

以下是官方和中文文檔對webpack的概括

At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into one or more bundles.

本質上,webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關系圖(dependency graph),其中包含應用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle。

起步

安裝

創建目錄,初始化npm。

mkdir webpack-demo && cd webpack-demo
cnpm init
cnpm install webpack --save-dev

說明:

  • cnpm是淘寶npm鏡像,使用方法和npm一樣。可以幫助我們提升包的下載速度。
  • cnpm install {packeg_name} --save-dev,package_name為要下載的包名稱,--save-dev,表示將package-name添加到package.jsondevDependencies中。

創建兩個文件測試,index.htmlindex.js

index.html

<html>
  <head>
    <title>Getting Started</title>
  </head>
  <body>
    <script src="./dist/bundle.js"></script>
  </body>
</html>

其中,bundle.js是我們等會要生成的文件,先不用了解

index.js

function component() {
  var element = document.createElement('div');

  element.innerHTML = 'hello webpack'

  return element;
}

document.body.appendChild(component());

此時的目錄結構為:

webpack-demo
  node_modules
  src
     index.js
  index.html
  package.json

將項目搭建成上述結構,我們就能學習第一個命令webpack。我們的目標就是以index.js為入口,生成一個bundle.js文件,供index.html使用。

webpack src/index.js dist/bundle.js
Hash: 629328b9dd2012d414f7
Version: webpack 3.10.0
Time: 59ms
    Asset     Size  Chunks             Chunk Names
bundle.js  2.64 kB       0  [emitted]  main
   [0] ./src/index.js 170 bytes {0} [built]

如果出現上訴回應,就說說明執行成功。此時我們的項目結構是這樣的:

webpack-demo
  dist
     bundle.js
  node_modules
  src
     index.js
  index.html
  package.json

可以看到dist/bundle.js就是webpack替我們生成的。

在瀏覽器中打開index.html,可以看到hello webpack

我們來看bundle.js究竟是個什么東西。

cat dist/bundle.js
//// 一堆被注釋掉的代碼
function component() {
  var element = document.createElement('div');

  element.innerHTML = 'hello webpack'

  return element;
}

document.body.appendChild(component());
// 這段代碼是我們是從我們的index.js copy的。

可以看到,對于我們自己寫的函數,webpack會原封不動的copy過來。

配置文件

我們之前使用的webpack src/index.js dist/bundle.js其實可以使用一個配置文件來表述,比在終端中敲命令更加方便。

創建文件 webpack.config.js
此時:

  node_modules
  src
     index.js
  index.html
  package.json
  webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

說明:

  • 其中,require是node.js內置函數表示引入模塊,path是node.js內置模塊。
  • entry是入口文件,就是我們的index.js
  • outpath表示輸出目錄及文件名。

為了便于觀察,我們刪掉之前生成的dist目錄及其文件

我們執行命令:

webpack --config webpack.config.js

Hash: 629328b9dd2012d414f7
Version: webpack 3.10.0
Time: 59ms
    Asset     Size  Chunks             Chunk Names
bundle.js  2.64 kB       0  [emitted]  main
   [0] ./src/index.js 170 bytes {0} [built]

此時目錄結構:

webpack-demo
  dist
     bundle.js
  node_modules
  src
     index.js
  index.html
  package.json

在瀏覽器中查看index.html,依然可以看到hello webpack

需要注意的是配置文件命名不一定是webpack.config.js,可以自由命名,如果為webpack.config.js,在使用命令時,可以省略--config

如果覺得輸入webpack比較麻煩或陌生,可以這樣來使用:
package.json中加入如下代碼:

{
  "scripts":{
      "build":"webpack"
   }
}

以后我們在打包時,可以直接使用:

cnpm run build
以上是用webpack實現的最基本的構建過程。

可以看到,我們的index.html是我們自己創建的,如果我們配置了多個入口文件或者修改了出口文件,自己再來修改index.html是很麻煩的,我們使用一個插件:

cnpm install --save-dev html-webpack-plugin
plugins:[
    new HtmlWebpackPlugin({
        title:'webpack-demo'
    })
  ]

我們刪除根目錄下我們自己手寫的index.html

rm index.html
cnpm run build
dist 
  bundle.js
  index.html
  cat index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>webpack-demo</title>
  </head>
  <body>
  <script type="text/javascript" src="bundle.js"></script></body>
</html>

我們發現,我們剛才安裝的這個插件,已經幫我們書寫好了index.html
且引入了打包產生的js文件。這是非常方便的。

管理資源

除了javascript,還可以通過loader引入其他類型的文件,如css.

加載CSS

我們安裝style-loader

cnpm install --save-dev style-loader css-loader

修改webpack.config.js:

module:{
    rules:[
        {
            test:/\.csss$/,
            use:[
                'style-loader',
                'css-loader'
            ]
        }
    ]
  }

要嚴格按照如上寫法,避免遇到問題。
通過瀏覽器預覽,我們發現hello webpack變成了紅色。

加載圖片

cnpm install --save-dev file-loader

修改webpack.config.js:

{
    test: /\.(png|svg|jpg|gif)$/,
    use :[
        'file-loader'
        ]
}

放入一張圖片icon.pngsrc中。
修改index.js:

import MyImg from './icon.png';

var img = new Image();
img.src = MyImg;
element.appendChild(img);

我們通過build,發現此時我們的頁面上顯示了剛才添加的圖片,這張圖片被放在了dist中。

管理輸出

因為代碼改的比較頻繁,我們的dist目錄中的文件會越來越多,有的文件可能不再需要,所以,在每次構建前清理dist目錄,是比較好的做法,因為只會生成用到的文件。

cnpm install clean-webpack-plugin --save-dev

修改webpack.config.js:

const CleanWebpackPlugin = require('clean-webpack-plugin');
plugins:[
  new CleanWebpackPlugin(['dist'])
]

此時,執行build后,dist中的文件就不會再有不需要的文件了。

開發

現在我們有一個痛點,每次修改代碼后,要手動重新webpack,才能查看改動后的情況,其實webpack給我們提供了多個方案,讓我們在代碼發生變化后自動編譯代碼:

  • webpack watch mode
  • webpack dev server
  • webpack dev middleware

需要指出的是,這三種方案都比較常用,特別是在一些項目的腳手架中,都高頻使用這些項目,比如vue-cli

觀察者模式

修改package.json:

{
  scripts:{
    "watch":"webpack --watch"
  }
}

此時,我們在終端中輸入:

`cnpm run watch`
> webpack-demo@1.0.0 watch /Users/liuhao/Desktop/webpack-demo
> webpack --watch

clean-webpack-plugin: /Users/liuhao/Desktop/webpack-demo/dist has been removed.

Webpack is watching the files…

Hash: a6eb44b735ce8b5f1f68
Version: webpack 3.10.0
Time: 689ms
                               Asset       Size  Chunks             Chunk Names
22f56d054f6abc3b0683e95a6a3f5150.png    95.6 kB          [emitted]  
                           bundle.js    20.3 kB       0  [emitted]  main
                          index.html  183 bytes          [emitted]  
   [0] ./src/icon.png 82 bytes {0} [built]
   [1] ./src/index.js 333 bytes {0} [built]
   [2] ./src/style.css 1.04 kB {0} [built]
   [3] ./node_modules/.0.28.9@css-loader!./src/style.css 330 bytes {0} [built]
    + 4 hidden modules
Child html-webpack-plugin for "index.html":
     1 asset
       [2] (webpack)/buildin/global.js 509 bytes {0} [built]
       [3] (webpack)/buildin/module.js 517 bytes {0} [built]
        + 2 hidden modules
Hash: 0eb719c26b33a7a1afe0
Version: webpack 3.10.0
Time: 28ms
     Asset       Size  Chunks             Chunk Names
 bundle.js    20.3 kB       0  [emitted]  main
index.html  183 bytes          [emitted]  
 + 1 hidden asset
   [1] ./src/index.js 337 bytes {0} [built]
    + 7 hidden modules
Child html-webpack-plugin for "index.html":
     1 asset
       4 modules

可以看到webpack watch模式開啟后,webpack進程沒有退出,一直在監聽程序變動,我們手動改動某一個位置,webpack又會自動編譯。這種方式的弊端就是,我們要觀察頁面,還是得手動刷新瀏覽器。

webpack-dev-server

如果說webpack --wacth只是webpack自帶的一個簡單工具,那么webpack-dev-server就非常有用了。它提供一個簡單的web服務器,能夠實時重新加載。webpack-dev-serverwebpack的另外一個項目,且出自于官方。

cnpm install --save-dev webpack-dev-server

修改webpack.config.js:

devServer:{
  contentBase:'./dist'
}

修改package.json:

{
  scripts:{
    "start":"webpack-dev-server --open"
  }
}

此時,我們執行cnpm start,就會在8080端口起來一個服務。渲染出html頁面。當我們修改代碼后,server會自動編譯,成功后會通知瀏覽器自動刷新,此時我們不要受到刷新瀏覽器,即可看到更新后的內容。

webpack-dev-middleware

webpack-dev-server一樣,webpack-dev-middleware也是由webpack官方進行維護的,但是能進行更多的自定義設置。

安裝expresswebpack-dev-middleware
其中,expressnode.js中優秀的web項目。

cnpm install --save-dev express webpack-dev-middleware

修改 webpack.config.js:

output: {
  publicPath:'/'
}

創建server.js:

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
 publicPath: config.output.publicPath
}));

// Serve the files on port 3000.
app.listen(3000, function () {
 console.log('Example app listening on port 3000!\n');
});

node.js server會啟動在3000端口。
我們添加一項script來快速啟動server.js.

{
  “scripts”:{
    "server":"node server.js"
  }
}

了解node.js的同學都知道node命令用來干啥,不在贅述。
現在我們執行:

cnpm run server

此時也實現了自動編譯,如果還希望同步到瀏覽器,還需要使用另外一個項目,webpack-hot-middleware

以上,我們可以知道,webpack-dev-server是使用起來最方便的。
這些內容,可以幫助我們在開發中,做到心中有數,后面我將結合es6+vue.js+webpack來演示單頁應用的開發。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。