1. 程式人生 > >webpack-dev-server不能自動重新整理問題

webpack-dev-server不能自動重新整理問題

如果已經將 webpack 安裝到全域性中,則可以直接使用 webpack 命令;如果非全域性安裝需使用,使用專案內部的 webpack 命令的話,需要使用如下方式來執行 webpack 命令:
node_modules/.bin/webpack
值得注意的是,npm start 命令可以引導任務執行,自動使用專案內部的 webpack 等命令。
注:package.json中的script會安裝一定順序尋找命令對應位置,本地的node_modules/.bin路徑就在這個尋找清單中,所以無論是全域性還是區域性安裝的Webpack,你都不需要寫前面那指明詳細的路徑了。

使用webpack-dev-server中遇到不能瀏覽器無法自動重新整理的問題;尋找多方答案後明白了一些;

下面有一些需要注意的點:

1.webpack-dev-server並不能讀取你的webpack.config.js的配置output!!

你在webpack.config.js裡面的配置output屬性是你用webpack打包時候才起作用的,對webpack-dev-server並不起作用

2.webpack-dev-server打包生產的檔案並不會新增在你的專案目錄中!!它預設打包的檔名是bundle.js,不會真的出現在你的專案目錄中。

注意:你啟動webpack-dev-server後,你在目標資料夾中是看不到編譯後的檔案的,實時編譯後的檔案都儲存到了記憶體當中。因此很多同學使用webpack-dev-server進行開發的時候都看不到編譯後的檔案

webpack-dev-server支援兩種模式來自動重新整理頁面.

  • iframe模式(頁面放在iframe中,當發生改變時過載)
  • inline模式(將webpack-dev-sever的客戶端入口新增到包(bundle)中)

兩種模式都支援熱模組替換(Hot Module Replacement).熱模組替換的好處是隻替換更新的部分,而不是頁面過載.

iframe模式
使用這種模式不需要額外的配置,只需要以下面這種URL格式訪問即可

inline模式
1 當以命令列啟動webpack-dev-server時,需要做兩點:

在命令列中新增–inline命令
在webpack.config.js中新增devServer:{inline:true}//這個也可以不用。
2 當以Node.js API啟動webpack-dev-server時,我們也需要做兩點:

由於webpack-dev-server的配置中無inline選項,我們需要新增webpack-dev-server/client?http://«path»:«port»/到webpack配置的entry入口點中.
將新增到html檔案中

    var config = require("./webpack.config.js");
    var webpack = require('webpack');
    var WebpackDevServer = require('webpack-dev-server');

config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/");

var compiler = webpack(config);
var server = new WebpackDevServer(compiler, {
    contentBase:'build/',
    publicPath: "/assets/"
});
server.listen(8080);

示例:
自動重新整理的配置方法(inline模式):
我習慣的做法是在專案的package.json裡面新增
如下程式碼親測有效:
專案結構圖:
這裡寫圖片描述

webpack.config.js

 /**
 * Created by DreamCatcher on 2017/11/1.
 * 如果沒有這個配置檔案,需要使用如下命令手動打包:node_modules\.bin\webpack js\requireAddDiv1.js dist\bundle.js
 * 如果有這個配置檔案,只需要使用如下命令就可以了:node_modules\.bin\webpack
 */
var webpack = require("webpack");
module.exports = {
    devtool: "eval-source-map",//生成Source Maps
    entry: "./js/requireAddDiv1.js",
    output: {
        path: __dirname + "/dist",
        filename: "bundle.js"
    },
    module: {
        /*在webpack2.0版本已經將 module.loaders 改為 module.rules 為了相容性考慮以前的宣告方法任然可用,
      同時鏈式loader(用!連線)只適用於module.loader,
      同時-loader不可省略
      */
        /*loaders: [
            {
                test: "/(\.jsx|\.js)$/",
                loader: "babel-loader"
            },
            {
                //test: /\.\/css\/*\.css$/,//這種方式精確定位
                test: "/\.css$/",
                loader: "style-loader!css-loader"//這種方式只有 loaders 可以使用 rules 不可以
            }
        ]*/
        //以下是使用 rules 的方式:
        rules: [
            {
                test: "/(\.jsx|\.js)$/",
                use: {
                    loader: "babel-loader"
                },
                exclude: /node-modules/ //注意這裡沒有使用引號
            },
            {
                test: "/\.css$/",
                use: [ //引入多個loader的方法
                    "style-loader",
                    {
                        loader: "css-loader",
                        options: {
                            // modules: true // 設定css模組化,詳情參考https://github.com/css-modules/css-modules
                        }
                    },
                    /*{
                        loader: 'postcss-loader',
                        // 在這裡進行配置,也可以在postcss.config.js中進行配置,詳情參考https://github.com/postcss/postcss-loader
                        options: {
                            plugins: function () {
                                return [
                                    require('autoprefixer')
                                ];
                            }
                        }
                    }*/
                ]
            }
        ]
    },
    plugins: [
        new webpack.BannerPlugin('版權所有,盜版必究!')
    ]
};

注:“__dirname”是node.js中的一個全域性變數,它指向當前執行指令碼所在的目錄。

webpack提供兩個工具處理樣式表,css-loader 和 style-loader,二者處理的任務不同,css-loader使你能夠使用類似@import 和 url(…)的方法實現 require()的功能,style-loader將所有的計算後的樣式加入頁面中,二者組合在一起使你能夠把樣式表嵌入webpack打包後的JS檔案中。

如果需要使用到 postcss-loader, 需要首先安裝postcss-loader 和 autoprefixer(自動新增字首的外掛)

npm install –save-dev postcss-loader autoprefixer

或是在 package.json 檔案中進行配置。

devtool選項 配置結果
source-map 在一個單獨的檔案中產生一個完整且功能完全的檔案。這個檔案具有最好的source map,但是它會減慢打包速度;
cheap-module-source-map 在一個單獨的檔案中生成一個不帶列對映的map,不帶列對映提高了打包速度,但是也使得瀏覽器開發者工具只能對應到具體的行,不能對應到具體的列(符號),會對除錯造成不便;
eval-source-map 使用eval打包原始檔模組,在同一個檔案中生成乾淨的完整的source map。這個選項可以在不影響構建速度的前提下生成完整的sourcemap,但是對打包後輸出的JS檔案的執行具有效能和安全的隱患。在開發階段這是一個非常好的選項,在生產階段則一定不要啟用這個選項;
cheap-module-eval-source-map 這是在打包檔案時最快的生成source map的方法,生成的Source Map 會和打包後的JavaScript檔案同行顯示,沒有列對映,和eval-source-map選項具有相似的缺點;

上述選項由上到下打包速度越來越快,不過同時也具有越來越多的負面作用,較快的打包速度的後果就是對打包後的檔案的的執行有一定影響。對小到中型的專案中,eval-source-map是一個很好的選項,再次強調你只應該開發階段使用它。

Loaders和Plugins常常被弄混,但是他們其實是完全不同的東西,可以這麼來說,loaders是在打包構建過程中用來處理原始檔的(JSX,Scss,Less..),一次處理一個,外掛並不直接操作單個檔案,它直接對整個構建過程其作用。

package.json

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "My test of webpack",
  "main": "js/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --inline --content-base"
  },
  "keywords": [
    "webpack",
    "test"
  ],
  "author": "slHuang",
  "license": "ISC",
  "devDependencies": {
    "webpack": "3.8.1",
    "css-loader": "^0.28.7",
    "style-loader": "^0.19.0",
    "webpack-dev-server": "^2.9.3"
  }
}

這樣通過npm start命令就能啟動 inline模式了,當然也可以具體的輸入webpack-dev-server命令

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test webpack</title>
</head>
<body>
    <h3>This is my first test.</h3>
    <script src="bundle.js"></script>
</body>
</html>

關鍵的是你的index.html也就是你的專案入口的html檔案裡面引用這個bundle.js檔案需要直接引用根目錄下面的!一定不能寫 webpack.config.js 中 output 中配置的路徑,比如:dist/bundle.js

不能引用你webpack配置的bundle.js檔案目錄,webpack配置的這個bundle.js檔案,只有在你手動打包webpack之後才會改變!

requireAddDiv1.js

/**
 * Created by DreamCatcher on 2017/11/1.
 */
require("!style-loader!css-loader!../css/index.css");
var div = document.createElement("div");
div.innerHTML = "Added second div.";
document.body.appendChild(div);


var div2 = document.createElement("div");
div2.innerHTML = "Added second div2.";
document.body.appendChild(div2);

index.css

body {
    background-color: yellow;
    color: blue;
}

通過 npm start 啟動專案,chrome 裡面輸入以下路徑:http://localhost:8080/
頁面就可以打開了。

然後,就是見證奇蹟的時候了:
隨便修改 index.css 中的一個屬性,比如將 color 改成 red
這個時候,編譯器就會自動編譯:
這裡寫圖片描述

這時候 chrome 中頁面就會自動重新整理,並且當前修改的屬性,在頁面上正常表現出來了,文字顏色變成了 red。

總結下就是:webpack裡面配置的bundle.js需要手動打包才會變化目錄可以由你自己指定!webpack-dev-server自動檢測變化自動打包的是開發環境下的bundle.js,打包路徑由你的contentBase決定!兩個檔案是不一樣的

另外,停止 webpack-dev-server ,只需要在命令視窗中 ctrl + c 就可以了。

後面,還試了另一種配置:
接上面的示例,需要做如下修改:
1、將 webpack.config.js 新增如下配置:

module.exports = {
    ...
    devServer: {
        contentBase: "./",//本地伺服器所載入的頁面所在的目錄
        historyApiFallback: true,//不跳轉
        inline: true,//實時重新整理
        hot: true//hot module replacement. Depends on HotModuleReplacementPlugin
      } 
    ...
    plugins: {
        ...
        new webpack.HotModuleReplacementPlugin()
        ...
    }
}

2、在package.json中的scripts物件中新增如下命令,用以開啟本地伺服器:

 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --open" //這裡的 open 是指執行 server 後自動開啟 index.html頁面
  },

啟動 server:
npm run server

這樣也可以了。