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