Vue處理靜態資源:public、assets目錄


前言: webpack中的require解析

首先明確一點,在項目中的webpack.config.js等項目配置文件中使用的require屬於nodejs范疇,而進入index.js后,加載的組件中的require都屬於webpack的解析范疇。

webpack中require的用法:

let url = "@/assets/images/carousel/logo.svg"
require(url)    //報錯

let url = "logo.svg"
require("@/assets/images/carousel/"+url); //正確

這是因為你修改頁面后,webpack進行編譯,等待編譯完,需要進行工程的打包,然后打包正確,才能熱加載運行並刷新頁面。
如果require中傳入的是個變量,它有可能是計算機系統中的任何目錄下的任何文件,那么在打包靜態資源時它有可能會將你的電腦整個磁盤遍歷一遍(它很傻)。所以至少需要給出在哪個路徑下,這樣才能精確的將那個路徑下的對應文件打包,然后在代碼運行時,直接用對應文件名生成正則匹配(因為打包后的文件,可能有hash值。不能直接查文件名),找到后,加載到代碼中。

所以,請記住盡可能詳細的指定require中的路徑,然后拼接變量.

接下來說下打包后的路徑問題:

webpack將項目中的靜態資源編譯打包后,生成的路徑已經不是原來的那個路徑了。如

src/assets/image/logo.jpg

編譯后可能變成

dist/public/image/logo.1d997ea3.jpg

而通過require("src/assets/image/logo.jpg"),會自動找到並加載dist/public/image/logo.1d997ea3.jpg文件

Vue 是如何處理靜態資源的?

Vue 靜態資源可以通過兩種方式進行處理:

1、在 JavaScript 被導入或在 template/CSS 中通過相對路徑被引用。這類引用會被 webpack 處理(如:assets 目錄的文件)

2、放置在 public 目錄下或通過絕對路徑引用。這類資源將會直接被拷貝,而不會經過 webpack 的處理

一、URL 轉換規則

1、<template>部分的路徑處理

Vue Loader 在編譯單文件組件中的 <template> 塊時,它也會將所有遇到的資源 URL 轉換為 webpack 模塊請求。(這樣我們就沒必要手動調用require了,而是交給vue-loader處理了)

vue-loader默認可以處理的標簽/特性的組合如下:

{
  video: ['src', 'poster'],
  img: 'src',   //即img元素上的src屬性
  source: 'src',  //source元素上的src屬性
  image: 'xlink:href'
}

面對上面的標簽組合,vue-loader會自動進行資源url的轉換。

轉換規則:
a、如果路徑是絕對路徑,會被原樣保留。如/src/assets/image/login/title.png

//代碼
<template>
   <img src="/src/assets/image/login/title.png" alt="">
</template>

//渲染后html頁面
<img data-v-70c98a68="" src="/src/assets/image/login/title.png" alt="">
//當然這個圖片是無法展示的,因為編譯后title.png已不在src/assets/image/login下了

b、如果路徑以 . 開頭,將會被看作相對的模塊依賴。如 ./titlea.png

//代碼
<img src="./titlea.png" alt="">

//渲染后html頁面
<img data-v-70c98a68="" src="/static/img/titlea.1e9fa570.png" alt="">

c、如果路徑以 @ 開頭,也會被看作模塊依賴。如果你的 webpack 配置中給 @ 配置了 alias,這就很有用了。所有 vue-cli 創建的項目都默認配置了將 @ 指向 /src

//代碼
<img src="@/assets/image/login/title.png" alt="">

//渲染后html頁面
<img data-v-70c98a68="" src="/static/img/title.1e9fa570.png" alt="">

d、如果路徑以 ~ 開頭,其后的部分將會被看作模塊依賴,既可以加載含有別名的靜態資源,又可以加載node-modules中的資源。如

//代碼
<img src="~@/assets/image/login/title.png" alt="">
//渲染后html頁面
<img data-v-70c98a68="" src="/static/img/title.1e9fa570.png" alt="">


//代碼
<img src="~[npm包名]/xxx/logo.png" alt="">
//渲染后的html頁面
<img data-v-70c98a68="" src="/static/img/logo.2f53e458.png" alt="">

2、<style>部分的路徑處理

由於vue-loader在處理style時,采用的是style-loader,所以可能 和上面<template>部分的轉換規則不太一樣。
在vue-loader的內部使用了如下的配置(不一定配置,也有可能通過js直接給rules賦值):

//在vue-loader的內部使用css-loader
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        loader: 'css-loader',
        options: {  
          url: true, //默認選項
        },
      },
    ],
  },
};

url為true時,則意味着可以將url中的字符串通過require()加載進來。

轉換規則

a、如果路徑是絕對路徑,會被原樣保留。如/src/assets/image/login/title.png

//代碼
<style scoped>
.login-wrap {
  background-image: url("/src/assets/image/login/title.png");
}
</style>

//渲染后css
.login-wrap[data-v-70c98a68] {
  background-image: url(/src/assets/image/login/title.png);
}

同樣這個圖片是無法展示的,因為編譯后title.png已不在src/assets/image/login下了

b、如果路徑以 . 開頭,將會被看作相對的模塊依賴。如 ./titlea.png

//代碼
<style scoped>
.login-wrap {
  background-image: url("./titlea.png");
}
</style>

//渲染后css
.login-wrap[data-v-70c98a68] {
  background-image: url(/static/img/titlea.1e9fa570.png);
}

c、如果路徑以 ~ 開頭,其后的部分將會被看作模塊依賴,即可以加載含有別名的靜態資源,又可以加載node-modules中的資源。如

//代碼
<style scoped>
.login-wrap {
  background-image: url("~[npm包名]/logo.png");
}
</style>

//渲染后css
.login-wrap[data-v-70c98a68] {
  background-image: url(/static/img/logo.e05643fc.png);
}
//代碼
<style scoped>
.login-wrap {
  background-image: url("~@/assets/image/login/bg.png");
}
</style>

//渲染后css
.login-wrap[data-v-70c98a68] {
  background-image: url(/static/img/bg.1d997ea3.png);
}

注意: 和上面的<template>相比,唯獨少了直接用@開頭的方式url("@/assett/logo.png"),所以下面寫法是錯誤的

//代碼
<style scoped>
.login-wrap {
  background-image: url("@/assets/image/login/bg.png");
}
</style>

二、從相對路徑導入(assets 目錄)

當在 JavaScript、CSS 或 *.vue 文件中使用相對路徑 (必須以 . 開頭) 引用一個靜態資源時,該資源將會被包含進 webpack 的依賴圖中。編譯過程中,所有諸如 <img src="...">background: url(...) 和 CSS @import 的資源 URL 都會被解析為一個模塊依賴。

例如,url(./image.png) 會被翻譯為 require('./image.png'),而:

<img src="./image.png">

將會被編譯到:

h('img', { attrs: { src: require('./image.png') }})

在其內部,Vue 通過 file-loader 用版本哈希值和正確的公共基礎路徑來決定最終的文件路徑,再用 url-loader 將小於 4kb 的資源內聯,以減少 HTTP 請求的數量。

可以通過 chainWebpack 調整內聯文件的大小限制。例如,下列代碼會將其限制設置為 10kb:

// vue.config.jsmodule.exports = {
  chainWebpack: config => {
    config.module      .rule('images') .use('url-loader') .loader('url-loader') .tap(options => Object.assign(options, { limit: 10240 })) }}

 

三、public 文件夾

任何放置在 public 文件夾的靜態資源都會被簡單的復制,而不經過 webpack 。需要通過絕對路徑來引用。

注意 Vue 推薦將資源作為模塊依賴圖的一部分導入,這樣會通過 webpack 的處理並獲得如下好處:

1、腳本和樣式表會被壓縮且打包在一起,從而避免額外的網絡請求。

2、文件丟失會直接在編譯時報錯,而不是到了用戶端才產生 404 錯誤。

3、最終生成的文件名包含了內容哈希,因此你不必擔心瀏覽器會緩存它們的老版本。

public 目錄提供的是一個應急手段,當通過絕對路徑引用時,需要留意應用會部署到哪里。如果沒有部署在域名的根部,需要為你的 URL 配置 publicPath 前綴:

在 public/index.html 或其它通過 html-webpack-plugin 用作模板的 HTML 文件中,需要通過 <%= BASE_URL %> 設置鏈接前綴:

<link rel="icon" href="<%= BASE_URL %>favicon.ico">

在模板中,首先需要向你的組件傳入基礎 URL:

data () {
  return {
    publicPath: process.env.BASE_URL
  }
}

然后:

<img :src="`${publicPath}my-image.png`">

如publicPath設置為'/','/hls265/h265.m3u8'即可訪問:

 

 

 

 

 參考:https://cloud.tencent.com/developer/article/1776658

 轉自:https://segmentfault.com/a/1190000018472635


免責聲明!

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



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