webpack 配置 publicPath的理解


  在學習webpack的時候,配置文件中有一個publicPath屬性,一直不是很明白它到底是怎么用,也查了很多資料,得到最多的說法是當打包的時候,webpack會在靜態文件路徑前面添加publicPath的值,當我們把資源放到CDN上的時候,把publicPath的值設為CDN的值就可以了。但是在使用webpack 進行開發的時候,得到的結果卻和該說法不是很一致,經過一段時間的摸索,好像是懂了一點點,至少在簡單的配置中不會報錯,在這里記一下,做一個總結.

  我們在使用webpack 進行開發的時候,通常是使用webpack-dev-server 進行開發,因為它的熱加載,實時更新。而在生產上版本的時候,則是使用wepback命令進行打包,生成一個js 文件。上面的publicPath的使用說法適用於生產環境。當使用webpack命令進行打包上生產時,它確實是在靜態資源路徑前面加上publicPath的值。 但是當我們使用webpack-dev-server 進行開發時,它卻不是在靜態文件的路徑上加publicPath的值,相反,它指的是webpack-dev-server 在進行打包時生成的靜態文件所在的位置。也就是說publicPath的使用是分環境的。

  你可能有個疑問,webpack-dev-server會進行打包嗎?webpack-dev-server也會進行打包,代碼只要一變動,它就會打包,只不過它打包到的地方是計算機的內存,在硬盤中看不到。再具體一點,默認情況下,webpack-dev-server 會把打包后的文件放到項目的根目錄下,文件名是在output配置中的filename. 但是當有publicPath 配置的時候,就不一樣了。Webpack 會把所有的文件打包到publicPath指定的目錄下,就是相當於在項目根目錄下創建了一個publicPath目錄, 然后把打包成的文件放到了它里面,只不過我們看不到而已, 文件名還是output配置中的filename。

  現在使用webpack驗證一下。不過還要分兩種情況,手動創建index.html文件 和html-webpack-plugin 自動創建index.html文件。手動創建html 不常見,但是我在初學webpack的時候,確實是手動創建index.html的,也是折騰了好久。不管哪種情況,先把webpack 項目搭建起來.

  新建一個文件夾webpack-tut, 執行npm init -y, 創建package.json 文件,同時初始化為node 項目。再在里面新建 src 文件夾和webpack.config.js 配置文件。在src 里面再新建css文件夾,img文件夾,index.js。css 文件夾 有一個style.css 放置樣式,在img文件夾中放置一大一小兩張圖片, 小的圖片1kb, 大的圖片5kb.  index.js 作為入口文件,npm install webpack webpack-dev-server  css-loader style-loader  url-loader file-loader --save-dev 來安裝依賴. package.json中先寫兩個命令: 

"scripts": {
    "build": "webpack",
    "dev":"webpack-dev-server"
  },

webpack.config.js 如下

const path = require('path');

module.exports = {
    entry: path.join(__dirname, 'src/index.js'),
    output: {
        path: path.join(__dirname, 'dist'),
        filename:'bundle.js'
    },
    module: {
        rules:[
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.(png|jpg)$/,
                loader: 'url-loader',
                options: {
                    limit: 3000,
                    name: '[name].[hash:8].[ext]'
                }
            }
        ]
    }
}

  style.css 如下:

.small {
    width: 200px;
    height: 200px;
    background: url(../img/small.jpg) no-repeat;
}
.big {
    width: 500px;
    height: 350px;
    background: url(../img/big.jpg) no-repeat;
}

  index.js 如下

import './css/style.css';
import img from './img/big.jpg';

var imgElement = document.createElement('img');
imgElement.src = img;
document.body.appendChild(imgElement);

  手動創建index.html文件

  現在我們在項目根目錄中新建index.html, 整個index.html 如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Webpack Tut</title>
</head>
<body>
    <div class="small"></div>
    <div class="big"></div>
</body>
</html>

  現在最重要的問題是怎么引入打包后的js 文件,根據上面的分析,我們可以知道,當啟動webpack-dev-server的時候,它把打包后的文件放到根目錄下,並且文件名應為 bundle.js, 所以index.html文件中引入js 應該為 src="./bundle.js"

<body>
    <div class="small"></div>
    <div class="big"></div>
    <script src="./bundle.js"></script>
</body>

  現在npm run dev 啟動webpack-dev-server, 然后打開瀏覽器,輸入localhost:8080,  可以看到三張圖都顯示出來了,沒有問題,證明分析是正確的。

  現在執行npm run build 進行打包, 打包完成后,以訪問服務器的方式打開index.html,因為,打包后的文件是要發布到服務器上的。怎么使用這種方式 ?VS code 編輯器有一個擴展叫做Live Server,安裝之后,在index.html中右鍵,有一個 open with Live Server選項, 點擊,它會使用默認的瀏覽器以服務器的方式打開文件。這時你發現頁面空白,肯定是報錯了,打開控制台,bundle.js 文件沒有找到,這時想起來,bundle.js是打包到 dist 目錄下,修改index.html ,引入dist 下面的js.

<script src="./dist/bundle.js"></script>

  刷新瀏覽器,頁面只有一張圖片,大圖並沒有顯示出來,這是為什么呢?打開控制台, 點擊Elements 選項卡可以看到

  我們js動態插入的img圖片,和class=big 的div的background, 它們都是引用的根目錄下的圖片,但根目錄下並沒有這張圖片,dist 目錄下面有這張圖片,我們想要讓它引用dist下面的圖片, 這時想到webpack 進行打包的時候會把publicPath指定的路徑加到靜態資源路徑前面, 所以在webpack的配置文件中加入publicPath

  再執行npm run build重新打包,刷新瀏覽器,可以看到三張圖片. 再打開瀏覽器台,可以看到img 的路徑前面加了dist

  這時我們再來看看class=big的div的樣式

  我們在style.css的源代碼中是url(../img/big.jpg), 而在打包之后,它卻把url的路徑改成了dist, 因為打包后所有的靜態圖片都放到了dist 目錄下,沒有了 img 目錄。

  現在npm run dev  啟動webpack-dev-server , 在瀏覽器中輸入localhost:8080  一切正常,沒有錯誤, 我們來分析一下,這是為什么,首先要看一下,當啟動webpack-dev-server的時候,發生了什么

  整個項目運行在localhost:8080下面,也就是服務器地址是localhost:8080 , 這也是我們在瀏覽器中輸入localhost:8080的原因。當我們在瀏覽器中輸入服務器地址,服務器會尋找它下面的index.html文件,並返回給瀏覽器,因為我們的項目在webpack-tut目錄下啟動的,它下面有index.html,這沒有問題,瀏覽器在接受到index.html 就開始解析,它碰到script標簽就會向服務器請求js 文件,js的地址是dist/bundle.js,服務器就會在dist目錄下找bundle.js.  根據我們所知道的,當有publicPath 配置時,webpack-dev-server 會把打包后的資源放到publicPath 指定的目錄,也就是dist 目錄下,所以服務器是在dist 目錄下可以找到bundle.js,沒有問題,整個項目也沒有報錯。分析完了,但還是向下看一下吧,有意外的收獲

  接着向下看:wepback output is served from /dist/ , webpack 輸出(打包后的文件)放到了/dist/ 目錄下,這也證明了webpack-dev-server 進行打包時,它打包到了publicPath 指定的目錄。

  然后就沒有什么重要的了,hash, verison,wepback 開始進行打包,最后是time, 表示耗時799ms, webpack 完成了打包,打包后的文件列出來了,一個img,名稱為big.2a9adfd0.jpg,一個js 文件 bundle.js,還列了出打包所經歷的各種module, 最后顯示complied successful, 直到這時瀏覽器可以訪問了。

  現在我們知道了js, img等靜態文件所在的地址和名稱,可以嘗試訪問一下。在瀏覽器輸入localhost:8080/dist/bundle.js, 看到bundle.js文件,輸入localhost:8080/dist/ big.2a9adfd0.jpg, 看到了圖片,這也證明了我們的分析是正確的。

  其實有一個辦法,可以看到我們localhost服務器下的資源,也就是控制台中的source 面板。

  服務器下面有一個index.html 文件和dist 文件夾,這里也可以看到webpack-dev-server 打包生成了一個dist 文件夾。

  總結:當我們手動創建index.html, 並手動指定css 或js 靜態文件路徑時,保證path 和publicPath的設置一致就好了。

  自動創建index.html

  現在把index.html 刪除,然后通過html-webpack-plugin 自動創建index.html, 同時把dist 目錄刪掉。 npm install html-webpack-plugin --save-dev, webpack.config.js 修改如下

const path = require('path');

// 引入webpack 和 html-webpack-plugin插件
const webpack = require('webpack');
const htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: path.join(__dirname, 'js/index.js'),
    output: {
        path: path.join(__dirname, 'dist'),
        filename:'bundle.js',
        publicPath: '/dist/'
    },
    module: {
        rules:[
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.(png|jpg)$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: '[name].[hash:8].[ext]'
                }
            }
        ]
    },
    plugins: [
        new htmlWebpackPlugin() // 使用插件
    ]
}

   npm run dev 啟動服務器,瀏覽器,輸入localhost:8080,可以看到服務器下面,都沒有index.html 這個文件

  這是怎么一回事?看一下我們的配置文件,配置了publicPath,當有publicPath的時候,webpack-dev-server 會把所有打包好的文件都放到publicPath 指定的目錄下,也就是dist目錄,因為index.html文件是由webpack 打包生成的,所以它也在dist 目錄下,那么我們應該訪問服務器下面的dist 目錄,所以瀏覽器中應該輸入localhost:8080/dist/, 

  訪問成功了。再看一下控制台中的source 面板,

  可以看到localhost 本地服務器下面只有一個dist 目錄,dist 目錄有打包好的靜態資源,這也充分證明了,webpack-dev-server 會把所有的文件打包到publicPath指定的目錄。這樣訪問有點不太方便了,最簡單的辦法,就是把publicPath配置去掉,這樣webpack-dev-server就會把文件打包到根目錄下,localhost:8080就會訪問到。去掉之后重啟服務器。

 

  沒有問題。那么npm run build 打包到生產環境有沒有問題呢?打包成功之后,可以發現沒有問題。這是因為html和其它靜態資源是在同一個文件下, html文件直接訪問其它文件是不用加什么前綴路徑

  總結一下,在使用html-webpack-plugin 生成index.html時,publicPath是可以不用配置的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM