欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue CLI3搭建的項(xiàng)目中路徑相關(guān)問(wèn)題的解決

 更新時(shí)間:2018年09月17日 11:25:44   作者:billychan  
這篇文章主要介紹了Vue CLI3搭建的項(xiàng)目中路徑相關(guān)問(wèn)題的解決,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

這是開(kāi)頭

最近在試水 Vue CLI 3,并且嘗試配置一個(gè)多頁(yè)面(多應(yīng)用)項(xiàng)目出來(lái),期間又遇到各種路徑問(wèn)題,于是...于是有了下面的嘮叨。

以下都是基于 Vue CLI 3 來(lái)舉例說(shuō)明的,使用 2.x 版本的其實(shí)也類(lèi)似

首先,參考 官方文檔對(duì)靜態(tài)資源處理的說(shuō)明,并通過(guò)自己的實(shí)踐,可以總結(jié)出以下內(nèi)容

靜態(tài)資源可以通過(guò)兩種方式進(jìn)行處理:

1、以下情況下,資源不會(huì)被 webpack 處理,而是被直接拷貝:

  1. 放置在 public 目錄下,即使未被使用。
  2. 通過(guò)絕對(duì)路徑被引用,即以 / 開(kāi)頭的路徑。

2、以下情況下,資源會(huì)被 webpack 處理(URL的resolve、minify、uglify、轉(zhuǎn) base64 等):

  1. 使用 JavaScript 導(dǎo)入。
  2. 在 template/CSS 中通過(guò)相對(duì)路徑(即以 . 開(kāi)頭或直接以文件(夾)名開(kāi)頭)被引用。
  3. URL 以 ~ 開(kāi)頭,其后的任何內(nèi)容都會(huì)作為一個(gè)模塊請(qǐng)求被解析。
  4. URL 以 @ 開(kāi)頭,它也會(huì)作為一個(gè)模塊請(qǐng)求被解析(@ 是在 webpack 設(shè)置的 alias)。

我們應(yīng)該根據(jù)實(shí)際情況去選擇我們要引用的資源是否要被處理,然后用對(duì)應(yīng)的、正確的方式去引用它們以達(dá)到目的。以下對(duì)使用絕對(duì)路徑和相對(duì)路徑的方法和注意事項(xiàng)進(jìn)行描述。

使用絕對(duì)路徑

默認(rèn)情況下,Vue CLI 會(huì)假設(shè)你的應(yīng)用是被部署在一個(gè)域名的根路徑上(對(duì)應(yīng)選項(xiàng) baseUrl: '/'),例如 https://www.my-app.com/。如果應(yīng)用被部署在一個(gè)子路徑上,你就需要用這個(gè)選項(xiàng)指定這個(gè)子路徑。例如,如果你的應(yīng)用被部署在 https://www.my-app.com/my-app/,則設(shè)置 baseUrl 為 /my-app/。正因?yàn)橐陨系目赡芮闆r,我們應(yīng)該在打算引用純靜態(tài)資源(那些不被webpack處理的資源,一般就是 public 目錄下的資源)的時(shí)候,都確保使用 baseUrl 作為 URL 的開(kāi)頭,以下列舉在不同文件中配合 baseUrl 選項(xiàng)寫(xiě)絕對(duì)路徑的使用方法和注意事項(xiàng):

在入口html文件中使用

我們可以使用lodash template 語(yǔ)法插入 baseUrl:

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

在 *.vue 中使用

我們可以通過(guò) Vue CLI 提供的客戶端環(huán)境變量 process.env.BASE_URL 來(lái)獲取 baseUrl:

/* 在需要的組件中定義 baseUrl,然后在 <template> 下使用 */
<template>
  <div id="app">
    <img :src="imgUrl">
    <img :src="`${baseUrl}imgs/my_image.png`">
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      baseUrl: process.env.BASE_URL,
      isBigImg: Math.random() > 0.5
    }
  }
  computed: {
    // 動(dòng)態(tài)地獲取不同的靜態(tài)資源
    imgUrl() {
      if (this.isBigImg) {
        return `${baseUrl}imgs/my_image_big.png`
      } else {
        return `${baseUrl}imgs/my_image.png`
      }
    }
  }
};
</script>

 
/* 個(gè)人建議可以在全局定義,減去在每個(gè)組件內(nèi)定義的麻煩
Vue.prototype.$baseUrl = process.env.BASE_URL
// 在 <template> 下使用
<img :src="`${$baseUrl}imgs/my_image.png`">

在其他 js 模塊中使用

import axios from 'axios';

const baseUrl = process.env.BASE_URL;

axios.defaults.baseURL = `http://www.example.com${baseUrl}api/`

在樣式文件中使用(以 sass/scss 為例)

因?yàn)?sass 文件中無(wú)法獲取環(huán)境變量或 webpack 內(nèi)的配置,于是最直接的方法就是自定義一個(gè)變量,然后在每個(gè)需要使用到它的文件引用它。

// config.scss
$baseUrl: "/";

// icon.scss

@import "config"

.icon-test {
  display: inline-block;
  background: url($baseUrl + 'imgs/icon_test.png') no-repeat;
  width: 10px;
  height: 10px;
}

這樣做還是有比較大的麻煩:

  • 如果生產(chǎn)環(huán)境和開(kāi)發(fā)環(huán)境的 baseUrl 不同,每次轉(zhuǎn)換環(huán)境去編譯都要去手動(dòng)修改這個(gè)變量,十分之麻煩而且可能出現(xiàn)錯(cuò)誤;
  • 兩處地方相同的定義,不方便代碼的維護(hù);
  • 在后續(xù)講到的關(guān)于 相對(duì)路徑 的坑會(huì)涉及到,每次引用 config.scss 的路徑并不一定是一樣的,且很容易出現(xiàn)編譯錯(cuò)誤;

那么,有沒(méi)有什么辦法能避免人工操作、避免多次的定義并且避免使用可能潛在錯(cuò)誤的引用呢?幸虧的確是有的! sass-loader 提供了一個(gè) data 選項(xiàng),可以為全局注入變量或樣式文件;

// vue.config.js

const baseUrl = process.env.NODE_ENV === 'production' ? '/sub/' : '/';

module.exports = {
  baseUrl,

  css: {
    loaderOptions: {
      sass: {
        data: `$baseUrl: "${baseUrl}";`
      }
    }
  }
}

這樣我們就可以在全局的 `sass` 文件中使用 `$baseUrl` 這個(gè)變量了,而且在只定義一次的情況下,能根據(jù)編譯環(huán)境變化而變化。

使用相對(duì)路徑

使用相對(duì)路徑也會(huì)存在一些坑,接下來(lái)會(huì)列舉常見(jiàn)的關(guān)于相對(duì)路徑的坑與解決方法:

JavaScript 動(dòng)態(tài)引用資源,編譯沒(méi)報(bào)錯(cuò),但頁(yè)面上請(qǐng)求返回 404

有時(shí)候我們需要使用 JavaScript 動(dòng)態(tài)的引用某些資源,且希望這些資源被 webpack 一同打包,我們先看這種做法:

computed: {
  background () {
    return `./bgs/${this.id}.jpg`
  }
}

我們會(huì)發(fā)現(xiàn)打包沒(méi)報(bào)錯(cuò),但是在頁(yè)面上可以發(fā)現(xiàn)這些資源的請(qǐng)求都是 404。這是因?yàn)轭?lèi)似 ./bgs/${this.id}.jpg 這樣的動(dòng)態(tài)字符串在打包階段不會(huì)被 webpack 識(shí)別為依賴(lài),資源也就不會(huì)被打包了。為了讓 webpack 識(shí)別這些依賴(lài),我們可以這樣做:

computed: {
  background () {
    return require('./bgs/' + this.id + '.jpg')
  }
}

通過(guò)使用 require() 讓 webpack 將括號(hào)內(nèi)的 URL 識(shí)別為一個(gè)依賴(lài)并傳入對(duì)應(yīng)的 loader 進(jìn)行處理。

要特別注意,以上的例子中,./bgs/ 目錄下的所有圖片都會(huì)被打包,因?yàn)?webpack 無(wú)法得知頁(yè)面在運(yùn)行時(shí)會(huì)使用哪張圖片,所以 webpack 會(huì)把所有的圖片都打包了。

在 sass 中使用相對(duì)路徑引用圖片或字體文件,編譯報(bào)錯(cuò)

先來(lái)看一個(gè)例子:

// 文件目錄
// src
// |--assets
// |  |
// |  |-fonts
// |  |  |- iconfont.eot
// |  |
// |  |-css
// |    |
// |    |-iconfont.scss
// |
// |--app.vue
// iconfont.scss
@font-face {
  font-family: "iconfont";
  src: url("../fonts/iconfont.eot");
  ...
}
// app.vue
<style lang="scss">
@import './assets/css/iconfont.scss'
</style>

往往我們?cè)诖虬臅r(shí)候會(huì)報(bào)錯(cuò)(以上例子會(huì)報(bào)錯(cuò)),說(shuō)找不到 iconfont.eot。 sass-loader 文檔中有對(duì) url() 進(jìn)行了單獨(dú)的說(shuō)明

Since Sass/libsass does not provide url rewriting, all linked assets must be relative to the output.

If you're just generating CSS without passing it to the css-loader, it must be relative to your web root.
If you pass the generated CSS on to the css-loader, all urls must be relative to the entry-file (e.g. main.scss).

大致意思就是, sass-loader 并不提供 url 的重寫(xiě),所有的 scss 文件被 sass-loader 處理成最終的 CSS 后(編譯過(guò)程中 url 不會(huì)被重寫(xiě)即保持原樣),再傳遞給 css-loader 處理。也就是說(shuō),所有的 url 都是相對(duì)于輸出的!在 Vue CLI 搭建的項(xiàng)目中,它們都是相對(duì)于使用這些 scss 文件的 vue 文件的。對(duì)于上例,是相對(duì)于 app.vue 的,因此報(bào)錯(cuò)。我們會(huì)很自然的會(huì)希望路徑的引用是相對(duì)于 scss 文件本身的,sass-loader 文檔中也給出了解決方案:

Add the missing url rewriting using the resolve-url-loader. Place it before the sass-loader in the loader chain.
Library authors usually provide a variable to modify the asset path. bootstrap-sass for example has an $icon-font-path. Check out this working bootstrap example.

第一個(gè)方法:使用 resolve-url-loader 來(lái)彌補(bǔ) sass-loader 缺失的 url 重寫(xiě)功能,注意要放到 sass-loader 以前調(diào)用。

第二個(gè)方法:Library 作者一般都會(huì)提供變量,用來(lái)設(shè)置資源路徑,如 bootstrap-sass 可以通過(guò) $icon-font-path 來(lái)設(shè)置。參見(jiàn)this working bootstrap example。

這樣看來(lái)解決的思路有兩種:

  1. 寫(xiě) url 的時(shí)候就寫(xiě) vue 文件相對(duì)于資源的路徑。這種方法較為暴力,當(dāng)項(xiàng)目層級(jí)復(fù)雜了之后容易寫(xiě)錯(cuò)路徑(加上現(xiàn)有的編輯器、IDE應(yīng)該認(rèn)為你寫(xiě)的路徑是錯(cuò)誤的)。當(dāng)同個(gè) scss 文件被多個(gè)不同層級(jí)的 vue 文件引用的時(shí)候,這種暴力的方法就行不通了!
  2. 使用第三方庫(kù)補(bǔ)充 sass-loader 的路徑重寫(xiě)功能,讓路徑的引用是相對(duì)于當(dāng)前 scss 文件本身的。這個(gè)方法能較好的解決問(wèn)題。

在這里提供一下我喜歡的方法。與其考慮 讓路徑的引用是相對(duì)于 scss 文件本身 或 讓路徑直接相對(duì)于 vue 文件,我們可以換個(gè)思路,讓所有路徑都是以根目錄往下找,并讓 webpack 對(duì)路徑進(jìn)行重寫(xiě),但是直接用 /src/ 這種絕對(duì)路徑的寫(xiě)法會(huì)讓這些資源不被 webpack 打包。在前文提及到的,webpack 有個(gè)強(qiáng)大的機(jī)制,也就是 ~,通過(guò)在 url 前面添加 ~ 可以告訴 webpack 要把它當(dāng)做一個(gè)模塊來(lái)處理,也就是會(huì)被 webpack 打包。配合 webpack 提供的別名 @(/src),我們可以對(duì)上例做修改:

// iconfont.scss
@font-face {
  font-family: "iconfont";
  src: url("~@/assets/fonts/iconfont.eot");
  ...
}

這樣子,通過(guò) webpack 對(duì)模塊的處理,可以正確通過(guò)編譯!這樣做的好處是可大大避免書(shū)寫(xiě)相對(duì)路徑可能產(chǎn)生的錯(cuò)誤,每次只需“無(wú)腦”從根目錄往下找就是了,又可以減小依賴(lài)、減少配置項(xiàng)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論