webpack 從入門到上線

webpack 是什麼

clipboard.png

一項技術、一個工具的出現,確定是爲了解決問題的。那麼,webpack 是爲了解決什麼問題?答案是:文件依賴管理。瀏覽器端的 Js, 出於安全的考慮,對本地文件沒有操做權限,不能引用其它 js, css 等文件。而 webpack 就是用來解決這個問題的,讓你的項目能夠很好地分文件、分模塊,並且它對外部文件的引入同時支持 cmd, amd 和 commondJs 這三種形式,夠有誠意。
或許你要說了,解決文件依賴,早在 require.js 和 sea.js 的時候,都已經解決了呀!那麼,webpack 在這方面,有哪些新的突破:css

  1. 支持引用各類拓展名的文件
  2. 可以在不依賴 gulp 或 grunt 的狀況下直接產出打包文件
  3. 支持實時編譯,瀏覽器同步刷新

這個時候,是否是很想唱一下王力宏的《惟一》:肯定你就是個人惟一!
OK,進入正題。html

安裝與運行

目前,咱們的項目目錄結構是這樣的:vue

webpack_demo
|--src
|  |--pages
|  |  |--index
|  |  |  |--index.js
|--views_dev
|  |--index.html
|--webpack.config.js
|--package.json

安裝

在項目的根目錄執行:node

$ npm init // 生成項目依賴文件配置 package.json
$ npm install webpack -g // 全局安裝webpack
$ touch webpack.config.js // 在項目根目錄下,新建 webpack.config.js 文件

配置

而後,在如下3個文件,輸入內容:react

  1. 頁面 HTML 文件jquery

    // views_dev/index.html
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>首頁</title>
    </head>
    <body>
        <div>哈嘍,world</div>
        <script src="../asset/dev/main.js"></script>
    </body>
    </html>
  2. 頁面引用的 js 文件webpack

    // src/pages/index/index.js
    console.log('I am in index/index.js, haha4');
  3. webpack 打包配置git

    // webpack.config.js
    module.exports = {
    // 入口:要進行處理的實例(js)
    entry: './src/pages/index/index.js',
    // 出口:輸出配置
    output: {
        // 輸出到哪一個目錄
        path: './asset/dev/',
        // 靜態資源的引用路徑
        publicPath: '/asset/dev/',
        // 實例最終輸出的名字
        filename: '[name].js'
    }
    };

運行

運行 webpack 命令,進行打包。github

$ webpack

而後,搞定了,此時用瀏覽器打開 views_dev/index.html 這個文件,你會發現,打包成功了!web

clipboard.png

好的,你入門了,哈哈!接下去,我會詳細介紹單個頁面打包、多個頁面打包,以及最後的發佈上線。Now, go ~

單個頁面打包

這裏,你將學到:

  1. 引入其它 js 文件。是的,你將學會 模塊化
  2. 引入其它類型的文件,以 css 爲例。
  3. 實時編譯 + 瀏覽器同步刷新。爽!

如今,咱們的項目目錄,是這樣:

webpack_demo
|--src
|  |--pages
|  |  |--index
|  |  |  |--index.js
|  |  |  |--test.js
|  |  |  |--index.css
|  |--plugins
|  |  |--dialog
|  |  |  |--dialog.css
|  |  |  |--dialog.js
|--views_dev
|  |--index.html
|--webpack.config.js
|--package.json

引入其它 js 文件

  1. 經過相對路徑
    如今,咱們要在 src/pages/index.js 裏面引入 src/pages/test.js 文件。這樣作就能夠了:

    var Test = require('./test.js');

    你也許會問,此時,var Test 這個變量,獲得的是什麼?換個說法,怎麼控制 test.js 被導出到外部的內容。答案是:經過 module.exports. 例如:

    // index/test.js
    var str = "I am in test.js";
    module.exports = str;

    那麼,require('./test.js') 的值就是 "I am in test.js" 這個字符串。module.exports 能夠導出任何值。好比,咱們要導出 Object.

    module.exports = {
      aa: 'axxx',
      b: function() {}
    };
  2. 經過別名或模塊
    若是隻能使用相對路徑,那 webpack 就太不靠譜了。由於將有可能出現這樣 ../../../../libs/libs-tost/toast.js, 啊,想死!那麼,怎麼經過別名引入文件呢?假如,咱們想引入 src/plugins/dialog/dialog.js 這個彈窗。

    • webpack.config.js 中,配置別名

      // webpack.config.js
      module.exports = {
          resolve: {
              // 定義別名
              alias: {
                  plugins: 'D:/your/path/webpack_demo/src/plugins', // 別名能夠是目錄
                  myDialog: 'D:/your/path/webpack_demo/src/plugins/dialog/dialog.js' // 也能夠是文件
              }
          }
      }
    • 可使用了

      // src/index/index.js
      var Dialog = require('plugins/dialog/dialog.js'); // 方式一
      var Diaglog = require('myDialog'); // 方式二

      說明:require(TagPath)TagPath 若是以單詞開頭,將被認爲是模塊匹配,它會去找 node_modulesresolve.alias 下的模塊(或別名)。以方式一爲例,它的TagPath 是以 plugins 開頭(注意下:/plugins./plugins 都不叫以單詞開頭),因此能夠順利匹配到 resolve.alias.plugins. 在實際應用中,你常常會看到 require('jquery'), require('vue'), require('react'), 這些就是匹配到 node_modules 下已安裝的模塊。

引入其它類型的文件

webpack 的強大之處是,它容許你引入任何文件,好比:css, jpg, png. 那麼,問題來了,對於不一樣的文件,它要怎麼知道該如何分開處理呢?

// webpack.config.js
module.exports = {
    module: {
        loaders: [{
            test: /\.css$/,
            loader: 'style!css'
        }, {
            test: /\.js$/,
            loader: 'babel'
        }]
    }
};

上面的配置是說,對於拓展名是 .css 的文件,使用加載器 style!css(這邊中間有一個感嘆號,意思是:先是用 css 加載器處理,而後使用 style 加載器處理)。完整的寫法是:style-loader!css-loader, 其中,-loader能夠省略。而這裏的,style-loadercss-loader 就須要你 npm 安裝下了。

$ npm i style-loader -D
$ npm i css-loader -D

對於其它拓展名的處理,也是用一樣的方式來處理。

釋放雙手:自動編譯 + 瀏覽器同步刷新

你確定但願,這樣的功能。那麼,開始吧,喝杯咖啡!

  1. 自動編譯
    若是你只是想支持自動編譯,那麼很簡單。只要運行 $ webpack -w 就能夠開啓它的自動編譯功能。
  2. 用 webpack-dev-server 實現:自動編譯 + 瀏覽器同步刷新

    • 首先,你須要安裝 webpack-dev-server 這個包。

      $ npm i webpack-dev-server -D
    • 而後,我簡單介紹下它:webpack-dev-server 文檔

      • 運行時,它會啓動一個本地 Node 服務器,默認端口8080. 即:localhost:8080. 而且自動識別當前目錄下的 webpack.config.js 文件,來做爲 webpack 配置文件。
      • 產出的編譯後文件,不在 output.path 裏,而在它本身定義的內存。
      • 行內參數說明:

        • inline: 使用命令行模式。
        • content-base: 指定網站的根地址,若是你想指定爲項目根目錄,那麼 --content-base ./
        • hot: 開啓熱替換。通常用在 React 和 Vue 當中,咱們這裏不用。

    好了,那麼,啓動它吧:

    $ webpack-dev-server  --inline --content-base ./

    而後,你在瀏覽器中,訪問 http://localhost:8080/views_dev/index.html 就會發現,你修改代碼的時候,實時編譯,而且瀏覽器同步刷新了。(不過,要補充一下,觸發 webpack 從新編譯時,才能同步刷新瀏覽器。意味着,你修改 views_dev/*.html 的 HTML 文件時,瀏覽器,不會被刷新,由於它不會觸發 webpack 從新編譯。)

多頁面打包

如今,咱們加一點點配置,讓它支持多個頁面打包。以前,它是這樣的:

module.exports = {
    // 入口:要進行處理的實例(js)
    entry: './src/pages/index/index.js',
    // 出口:輸出配置
    output: {
        // 輸出到哪一個目錄
        path: './asset/dev/',
        // 靜態資源的引用路徑
        publicPath: '/asset/dev/',
        // 實例最終輸出的名字
        filename: '[name].js'
    },
    // 其它配置...
};

如今,咱們須要改下 entry 的配置,以下:

entry: {
    index: './src/pages/index/index.js',
    list: './src/pages/list/index.js',
    common: [
        './src/base/base.js',
        './src/base/base.css'
    ]
}

上面的配置意思是,會獨立打包3個實體。分別是 index, list, common. 知識點以下:

  1. 它支持多個文件打包在一塊兒,如這裏的 common 的配置。咱們通常,用來放公共基礎包。
  2. 咱們看到 output.filename = [name].js,這裏的 [name] 取自於 entry 的 key 值。意味着,他們最終打包的輸出是:

    webpack_demo
    |--asset
    |  |--dev
    |  |  |--index.js
    |  |  |--list.js
    |  |  |--common.js

上線

發佈上線,須要作什麼呢?也許是這樣:

  1. 把靜態資源生成到一個獨立的目錄下
  2. 壓縮
  3. 加上 md5
  4. html 和 css 中,引用的靜態資源須要替換。

哈哈,或許你還能想到不少。我就上面4步來講下實現方式。開始以前,咱們通常會這麼作:新建一個 webpack 的配置文件,用來作上線發佈的配置。好比,咱們一樣放在根目錄下,命名 webpack.config.build.js. 此時,你能夠這樣作:

$ webpack -p --config webpack.config.build.js

這裏的 -p 是 production 模式的意思,它會對 css, js 文件進行壓縮。後面 --config 就是指定這次運行的配置文件。

而後,咱們來解決上面的4個要求:

  1. 把靜態資源生成到一個獨立的目錄下 + md5 + css引用的資源替換

    // webpack.config.build.js
    module.exports = {
        output: {
            path: './asset/build/', // 文件編譯輸出路徑改爲 build
            publicPath: 'http://yourweb.com/asset/build/', // 這裏替換成線上實際地址,能夠修改 css 中對圖片資源的引用路徑。
            filename: '[name]_[hash:5].js' // 生成的文件名字,加上了5位的 hash值。固然了,位數和加hash的位置,你能夠本身定義,好比 '[name].js?[hash]'.
        },
        // 其它配置...
    };
  2. 壓縮。用 webpack -p 解決了。
  3. 替換 HTML 中靜態資源的路徑。能夠用 webpack 的插件,html-webpack-plugin 來作。或者,你對 gulp 仍是比較熟悉的話,用 gulp-prefix 來實現。這裏就不詳細寫配置了。

而後,恭喜你看完了!

相關文章
相關標籤/搜索