webpack開發部署技巧

如果你還沒有看第一篇 請先看下第一篇的基礎知識:webpack開發配置

開發技巧

啟用source-map

現在的代碼是合并以后的代碼,不利于排錯和定位,只需要在config中添加

...
  devtool: 'eval-source-map',
 ...

這樣出錯以后就會采用source-map的形式直接顯示你出錯代碼的位置。

配置webpack-dev-server代理

既然常用webpack做React一類的SPA,那么一個典型的例子就是前后端分離。后端是一個RESTful的server不管用什么寫的。假定在本機他是類似[http://localhost:5000/api/@*
]這類的請求,現在添加配置讓ajax請求可以直接proxy過去。

 devServer: {
        hot: true,
        inline: true,
        //其實很簡單的,只要配置這個參數就可以了
        proxy: {
          '/api/*': {
              target: 'http://localhost:5000',
              secure: false
          }
        }
    },

更多的方法可以看官方文檔 Webpack dev server proxy

使用preLoaders和postLoaders

也許你想在寫代碼的時候檢查自己的js是否符合jshint的規范,那么隆重推薦preLoaders和postLoaders,上一節我們已經非常了解loaders了,用它來處理各種類型的文件。perLoaders顧名思義就是在loaders執行之前處理的,webpack的處理順序是perLoaders - loaders - postLoaders。

在config文件中配置
module: {
...
    //和loaders一樣的語法,很簡單
    perLoaders: [
        {
            test: /\.jsx?$/,
            include: APP_PATH,
            loader: 'jshint-loader'
        }
    ]
}

...
//配置jshint的選項,支持es6的校驗
jshint: {
  "esnext": true
},

好了 現在每次npm run start的時候就可以看到jshint的提示信息啦

加載jQuery plugin或者其他legacy第三方庫

這個是非常有用的內容!

你的項目有時候會要加載各種各樣的第三方庫,一些老的庫不支持AMD或者CommonJS等一些先進的格式,比如一些jQuery的插件,它們都依賴jQuery,如果直接引用就會報錯 jQuery is not undefined這類的錯誤,有幾種方法解決

先創建一個jQuery plugin: plugin.js

(function ($) {
    const shade = "#556b2f";
    $.fn.greenify = function() {
        this.css( "color", shade );
        return this;
    };
}(jQuery));
第一種方法 使用webpack.ProvidePlugin
  ...
  plugins: [
    new HtmlwebpackPlugin({
      title: 'Hello World app'
    }),
    //provide $, jQuery and window.jQuery to every script
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    })
  ]
  ...

在js中引用

...
//這個也不需要了 因為$, jQuery, window.jQuery都可以直接使用了
//import $ from 'jquery';
import './plugin.js';
...
myPromise.then((number) => {
  $('body').append('<p>promise result is ' + number + ' now is ' + moment().format() + '</p>');
  //call our jquery plugin!
  $('p').greenify();
});
...

發現我們插入的p里面的顏色已經變成了綠色!

第二種方法 使用imports-loader

先安裝這個loader

npm install imports-loader --save-dev

然后在入口js中

//注意這種寫法 我們把jQuery這個變量直接插入到plugin.js里面了
//相當于在這個文件的開始添加了 var jQuery = require('jquery');
import 'imports?jQuery=jquery!./plugin.js';

//后面的代碼一樣
myPromise.then((number) => {
  $('body').append('<p>promise result is ' + number + ' now is ' + moment().format() + '</p>');
  //call our jquery plugin!
  $('p').greenify();
});

部署上線

剛才說的各種情況都是在開發時候的情況,那么假如項目已經開發完了,需要部署上線了。我們應該新創建一個單獨的config文件,因為部署上線使用webpack的時候我們不需要一些dev-tools,dev-server和jshint校驗等。

復制我們現有的config文件,命名為 webpack.production.config.js,將里面關于 devServer等和開發有關的東西刪掉。

在package.json中添加一個命令。

 "scripts": {
    "start": "webpack-dev-server --hot --inline",
    "build": "webpack --progress --profile --colors --config webpack.production.config.js"
  },

當要上線的時候,運行

npm run build

可以發現build文件夾中生成了所有東西。

分離app.js和第三方庫

現在我們build出來的只有一個bundle.js 如果第三方庫很多的話,會造成這個文件非常大,減慢加載速度,現在我們要把第三方庫和我們app本身的代碼分成兩個文件。

修改entry入口文件
  entry: {
    app: path.resolve(APP_PATH, 'index.js'),
    //添加要打包在vendors里面的庫
    vendors: ['jquery', 'moment']
  },
添加CommonsChunkPlugin
 plugins: [
    //這個使用uglifyJs壓縮你的js代碼
    new webpack.optimize.UglifyJsPlugin({minimize: true}),
    //把入口文件里面的數組打包成verdors.js
    new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'),
    new HtmlwebpackPlugin({
      title: 'Hello World app'
    })
  ]

添加完畢 運行npm run build

在build文件夾中發現如下結構

  • budle.js
  • index.html
  • vendors.js

生成多頁面

應用不可能都是SPA,不可能只生成一個html文件,如果想生成多個html頁面這么玩?其實也是很簡單的: 現在的需求是這樣的,有兩個頁面,一個叫index.html 它需要引用vendors.js和app.js這兩個文件,還有一個mobile.html頁面他要引用vendors.js和mobile.js這兩個文件。

首先新建一個叫mobile.js的入口文件,比app.js更簡單一些

import './main.scss';
import $ from 'jquery';
import 'imports?jQuery=jquery!./plugin.js';

$(document).ready(function() {
  let app  = document.createElement('div');
  app.innerHTML = '<h1>Hello World</h1>';
  document.body.appendChild(app);
  $('h1').greenify();
});

在config里面配置

 entry: {
    //三個入口文件,app, mobile和 vendors
    app: path.resolve(APP_PATH, 'index.js'),
    mobile: path.resolve(APP_PATH, 'mobile.js'),
    vendors: ['jquery', 'moment']
  },
  output: {
    path: BUILD_PATH,
    //注意 我們修改了bundle.js 用一個數組[name]來代替,他會根據entry的入口文件名稱生成多個js文件,這里就是(app.js,mobile.js和vendors.js)
    filename: '[name].js'
  },

原來我們是沒有模版文件的,原來利用的HtmlWebpackPlugin的默認模版。誰想到這偉大的插件還可以自定義模版。 所以新建一個專門放模版的文件夾templates,在里面加兩個模版文件index.html 和 mobile.html

index.html
<!DOCTYPE html>
<html>
  <head>
    <title>{%= o.htmlWebpackPlugin.options.title %}</title>
  </head>
  <body>
    <h3>Welcome to webpack</h3>
  </body>
</html>
mobile.html
<!DOCTYPE html>
<html>
  <head>
    <title>{%= o.htmlWebpackPlugin.options.title %}</title>
  </head>
  <body>
    <h3>Welcome to mobile page</h3>
  </body>
</html>

繼續配置config.js,現在讓HtmlwebpackPlugin可以生成多個文件

...
//Template的文件夾路徑
var TEM_PATH = path.resolve(ROOT_PATH, 'templates');
...
plugins: [
  ...
  //創建了兩個HtmlWebpackPlugin的實例,生成兩個頁面
  new HtmlwebpackPlugin({
    title: 'Hello World app',
    template: path.resolve(TEM_PATH, 'index.html'),
    filename: 'index.html',
    //chunks這個參數告訴插件要引用entry里面的哪幾個入口
    chunks: ['app', 'vendors'],
    //要把script插入到標簽里
    inject: 'body'
  }),
  new HtmlwebpackPlugin({
    title: 'Hello Mobile app',
    template: path.resolve(TEM_PATH, 'mobile.html'),
    filename: 'mobile.html',
    chunks: ['mobile', 'vendors'],
    inject: 'body'
  })
  ...
]

然后運行

npm run build

看看生成好的偉大的文件,沒問題!

  • app.js
  • mobile.js
  • vendors.js
  • index.html
  • mobile.html

看看引用的對應關系,完美!!

index.html
<body>
  <h3>Welcome to webpack</h3>
  <script src="vendors.js"></script><script src="app.js"></script>
</body>
mobile.html
<body>
  <h3>Welcome to mobile page</h3>
  <script src="vendors.js"></script><script src="mobile.js"></script>
</body>

生成Hash名稱的script來防止緩存

經典問題,代碼更新了,但是瀏覽器有緩存,到時候就傻了。 怎么解決,換名字唄。可以直接在后面加參數,也可以直接換掉文件名字。 webpack提供給了我們非常簡單的方法,基于文件的md5,只要把

output: {
  path: BUILD_PATH,
  //只要再加上hash這個參數就可以了
  filename: '[name].[hash].js'
},

運行完build以后,看看生成的文件,很完美~

index.html
<body>
  <h3>Welcome to webpack</h3>
  <script src="vendors.js"></script><script src="app.b6641abee64c999d95c1.js"></script>
</body>

好了,你現在了解webpack作為一個module bundler的精髓了吧,把我們的例子做成一個圖,幫助你理解一下。

image.png

文件壓縮

//使用插件html-webpack-plugin打包合并html
//使用插件extract-text-webpack-plugin打包獨立的css
//使用UglifyJsPlugin壓縮代碼
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require("webpack");
module.exports = {
    entry: {
        bundle : './src/js/main.js'
    },
    output: {
        filename: "[name]-[hash].js",
        path: __dirname + '/dist'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use: "css-loader"
                })
            }
        ]
    },
    resolve:{
            extensions:['.js','.css','.json']  //用于配置程序可以自行補全哪些文件后綴
    },

    plugins:[
        new HtmlWebpackPlugin({
            title: 'hello webpack',
            template:'src/component/index.html',
            inject:'body',
            minify:{ //壓縮HTML文件
                 removeComments:true,    //移除HTML中的注釋
                 collapseWhitespace:true    //刪除空白符與換行符
             }
        }),
        new ExtractTextPlugin("[name].[hash].css"),
        new webpack.optimize.UglifyJsPlugin({
            compress: {     //壓縮代碼
                dead_code: true,    //移除沒被引用的代碼
            },
            except: ['$super', '$', 'exports', 'require']    //混淆,并排除關鍵字
        })
    ]
};
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容

  • GitChat技術雜談 前言 本文較長,為了節省你的閱讀時間,在文前列寫作思路如下: 什么是 webpack,它要...
    蕭玄辭閱讀 12,706評論 7 110
  • 無意中看到zhangwnag大佬分享的webpack教程感覺受益匪淺,特此分享以備自己日后查看,也希望更多的人看到...
    小小字符閱讀 8,214評論 7 35
  • 一步一步學WebPack2 最近將webpack的使用總結一下,便于下一步的使用。本文通過若干的demo,讓你一步...
    wavesnow閱讀 572評論 0 5
  • 寫在開頭 先說說為什么要寫這篇文章, 最初的原因是組里的小朋友們看了webpack文檔后, 表情都是這樣的: (摘...
    Lefter閱讀 5,311評論 4 31
  • 咱們可以想下,節日的目的是什么?不就是表達了一個美好的祝愿嗎?對未來、生活、愛情、親情等的一種美好的祝愿啊!既然是...
    沈浪閱讀 996評論 0 2