webpack 配置 publicPath的理解

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

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

  你可能有個疑問,webpack-dev-server會進行打包嗎?webpack-dev-server也會進行打包,代碼只要一變更,它就會打包,只不過它打包到的地方是計算機的內存,在硬盤中看不到。再具體一點,默認狀況下,webpack-dev-server 會把打包後的文件放到項目的根目錄下,文件名是在output配置中的filename. 可是當有publicPath 配置的時候,就不同了。Webpack 會把全部的文件打包到publicPath指定的目錄下,就是至關於在項目根目錄下建立了一個publicPath目錄, 而後把打包成的文件放到了它裏面,只不過咱們看不到而已, 文件名仍是output配置中的filename。node

  如今使用webpack驗證一下。不過還要分兩種狀況,手動建立index.html文件 和html-webpack-plugin 自動建立index.html文件。手動建立html 不常見,可是我在初學webpack的時候,確實是手動建立index.html的,也是折騰了很久。無論哪一種狀況,先把webpack 項目搭建起來.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中先寫兩個命令: web

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

webpack.config.js 以下npm

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 以下:json

.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 以下app

<!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是能夠不用配置的。

相關文章
相關標籤/搜索