Vue CLI3搭建的项目中路径相关问题的解决

这是开头

最近在试水 Vue CLI 3,并且尝试配置一个多页面(多应用)项目出来,期间又遇到各种路径问题,于是...于是有了下面的唠叨。

以下都是基于 Vue CLI 3 来举例说明的,使用 2.x 版本的其实也类似

首先,参考 官方文档对静态资源处理的说明,并通过自己的实践,可以总结出以下内容

静态资源可以通过两种方式进行处理:

1、以下情况下,资源不会被 webpack 处理,而是被直接拷贝:

  1. 放置在 public 目录下,即使未被使用。
  2. 通过绝对路径被引用,即以 / 开头的路径。

2、以下情况下,资源会被 webpack 处理(URL的resolve、minify、uglify、转 base64 等):

  1. 使用 JavaScript 导入。
  2. 在 template/CSS 中通过相对路径(即以 . 开头或直接以文件(夹)名开头)被引用。
  3. URL 以 ~ 开头,其后的任何内容都会作为一个模块请求被解析。
  4. URL 以 @ 开头,它也会作为一个模块请求被解析(@ 是在 webpack 设置的 alias)。

我们应该根据实际情况去选择我们要引用的资源是否要被处理,然后用对应的、正确的方式去引用它们以达到目的。以下对使用绝对路径和相对路径的方法和注意事项进行描述。

使用绝对路径

默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上(对应选项 baseUrl: '/'),例如 https://www.my-app.com/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.my-app.com/my-app/,则设置 baseUrl 为 /my-app/。正因为以上的可能情况,我们应该在打算引用纯静态资源(那些不被webpack处理的资源,一般就是 public 目录下的资源)的时候,都确保使用 baseUrl 作为 URL 的开头,以下列举在不同文件中配合 baseUrl 选项写绝对路径的使用方法和注意事项:

在入口html文件中使用

我们可以使用lodash template语法插入 baseUrl:

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

在 *.vue 中使用

我们可以通过 Vue CLI 提供的客户端环境变量 process.env.BASE_URL 来获取 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: {
    // 动态地获取不同的静态资源
    imgUrl() {
      if (this.isBigImg) {
        return `${baseUrl}imgs/my_image_big.png`
      } else {
        return `${baseUrl}imgs/my_image.png`
      }
    }
  }
};
</script>

/* 个人建议可以在全局定义,减去在每个组件内定义的麻烦
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 为例)

因为 sass 文件中无法获取环境变量或 webpack 内的配置,于是最直接的方法就是自定义一个变量,然后在每个需要使用到它的文件引用它。

// 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;
}

这样做还是有比较大的麻烦:

  • 如果生产环境和开发环境的 baseUrl 不同,每次转换环境去编译都要去手动修改这个变量,十分之麻烦而且可能出现错误;
  • 两处地方相同的定义,不方便代码的维护;
  • 在后续讲到的关于 相对路径 的坑会涉及到,每次引用 config.scss 的路径并不一定是一样的,且很容易出现编译错误;

那么,有没有什么办法能避免人工操作、避免多次的定义并且避免使用可能潜在错误的引用呢?幸亏的确是有的! sass-loader 提供了一个 data 选项,可以为全局注入变量或样式文件;

// vue.config.js

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

module.exports = {
  baseUrl,

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

这样我们就可以在全局的 `sass` 文件中使用 `$baseUrl` 这个变量了,而且在只定义一次的情况下,能根据编译环境变化而变化。

使用相对路径

使用相对路径也会存在一些坑,接下来会列举常见的关于相对路径的坑与解决方法:

JavaScript 动态引用资源,编译没报错,但页面上请求返回 404

有时候我们需要使用 JavaScript 动态的引用某些资源,且希望这些资源被 webpack 一同打包,我们先看这种做法:

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

我们会发现打包没报错,但是在页面上可以发现这些资源的请求都是 404。这是因为类似 ./bgs/${this.id}.jpg 这样的动态字符串在打包阶段不会被 webpack 识别为依赖,资源也就不会被打包了。为了让 webpack 识别这些依赖,我们可以这样做:

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

通过使用 require() 让 webpack 将括号内的 URL 识别为一个依赖并传入对应的 loader 进行处理。

要特别注意,以上的例子中,./bgs/ 目录下的所有图片都会被打包,因为 webpack 无法得知页面在运行时会使用哪张图片,所以 webpack 会把所有的图片都打包了。

在 sass 中使用相对路径引用图片或字体文件,编译报错

先来看一个例子:

// 文件目录
// 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>

往往我们在打包的时候会报错(以上例子会报错),说找不到 iconfont.eot。 sass-loader 文档中有对 url() 进行了单独的说明

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 的重写,所有的 scss 文件被 sass-loader 处理成最终的 CSS 后(编译过程中 url 不会被重写即保持原样),再传递给 css-loader 处理。也就是说,所有的 url 都是相对于输出的!在 Vue CLI 搭建的项目中,它们都是相对于使用这些 scss 文件的 vue 文件的。对于上例,是相对于 app.vue 的,因此报错。我们会很自然的会希望路径的引用是相对于 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.

第一个方法:使用 resolve-url-loader来弥补 sass-loader 缺失的 url 重写功能,注意要放到 sass-loader 以前调用。

第二个方法:Library 作者一般都会提供变量,用来设置资源路径,如 bootstrap-sass可以通过 $icon-font-path 来设置。参见this working bootstrap example

这样看来解决的思路有两种:

  1. 写 url 的时候就写 vue 文件相对于资源的路径。这种方法较为暴力,当项目层级复杂了之后容易写错路径(加上现有的编辑器、IDE应该认为你写的路径是错误的)。当同个 scss 文件被多个不同层级的 vue 文件引用的时候,这种暴力的方法就行不通了!
  2. 使用第三方库补充 sass-loader 的路径重写功能,让路径的引用是相对于当前 scss 文件本身的。这个方法能较好的解决问题。

在这里提供一下我喜欢的方法。与其考虑 让路径的引用是相对于 scss 文件本身 或 让路径直接相对于 vue 文件,我们可以换个思路,让所有路径都是以根目录往下找,并让 webpack 对路径进行重写,但是直接用 /src/ 这种绝对路径的写法会让这些资源不被 webpack 打包。在前文提及到的,webpack 有个强大的机制,也就是 ~,通过在 url 前面添加 ~ 可以告诉 webpack 要把它当做一个模块来处理,也就是会被 webpack 打包。配合 webpack 提供的别名 @(/src),我们可以对上例做修改:

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

这样子,通过 webpack 对模块的处理,可以正确通过编译!这样做的好处是可大大避免书写相对路径可能产生的错误,每次只需“无脑”从根目录往下找就是了,又可以减小依赖、减少配置项。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue cli使用绝对路径引用图片问题的解决

    前言 Vue是什么,是一套构建用户界面的渐进式框架(官网解释),什么叫渐进式框架呢,简单回答就是主张最少,这些概念只能自己去看,自己去理解,一千个读者一千个哈姆雷特,不过多的解释.Vue官方文档 很全面的. Vue是近两年来比较火的一个前端框架(渐进式框架吧),本文将给大家详细介绍vue cli使用绝对路径引用图片问题的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看吧. 正文: 在页面中使用绝对路径可通过在js中用 require() 引入 data (){ return { sr

  • vue-cli中打包图片路径错误的解决方法

    最近第一次使用vue-cli构建项目,第一次打包部署到服务器上的时候出现图片加载不出来,结合网上的方法,终于给摸索出来.将项目部署到服务器上分为两种:一种是直接部署到服务器的根目录,另外一种是部署到服务器的子目录下 1.我们首先来说部署到根目录下 就是比如:www.****.com 找到项目中config文件夹下的index.js文件 将文件中的assetsPublicPath: '/',改成如下方框这样. 这样的目的是将绝对路径改成相对路径 如果放在根目录下,这样就可以了 2.放在子目录下 如

  • vue-cli webpack模板项目搭建及打包时路径问题的解决方法

    这里建议刚学vue的同学第一个小案例不要使用vue-cli进行操作,待对基本的api使用的比较顺手了之后再进行vue-cli的体验比较好.本人是一名后端开发人员,接触前端时间不长,这里有说的不好的地方,还请大家评论建议下. 1. 安装必要的环境准备 首先我们要能够暗转node.js,这个环境.百度搜索node,进入官网根据自己的操作系统进行下载即可.现在的版本都是自带npm的了.所以安装后,环境变量正常情况下会自动配置,开启一个命令行终端,输入node,npm,就可以看到相应的信息.那么说明安装

  • 解决vue-cli项目webpack打包后iconfont文件路径的问题

    在使用vue-cli创建vue项目时,可以自动生成webpack文件.使用 npm run build 即可打包发布生产文件,打包后的文件 webpack配置 可以看到使用url-loader处理后的文件是在static目录下生成fonts目录下的文件.全部样式文件打包在css目录下app.hash.css文件中. 但我们会发现发布后,会存在字体文件找不到的问题,查看css文件发现是iconfont字体文件的路径引用问题. 解决方法: 在build/utils文件中的下图所示位置添加../../

  • 解决vue-cli项目打包出现空白页和路径错误的问题

    vue-cli项目打包: 1. 命令行输入:npm run build 打包出来后项目中就会多了一个文件夹dist,这就是我们打包过后的项目. 第一个问题,文件引用路径.我们直接运行打包后的文件夹中的index.html文件,会看到网页一片空白,f12调试,全是css,js路径引用错误的问题. 解决:到config文件夹中打开index.js文件. 文件里面有两个assetsPublicPath属性,更改第一个,也就是更改build里面的assetsPublicPath属性: assetsPub

  • Vue CLI3搭建的项目中路径相关问题的解决

    这是开头 最近在试水 Vue CLI 3,并且尝试配置一个多页面(多应用)项目出来,期间又遇到各种路径问题,于是...于是有了下面的唠叨. 以下都是基于 Vue CLI 3 来举例说明的,使用 2.x 版本的其实也类似 首先,参考 官方文档对静态资源处理的说明,并通过自己的实践,可以总结出以下内容 静态资源可以通过两种方式进行处理: 1.以下情况下,资源不会被 webpack 处理,而是被直接拷贝: 放置在 public 目录下,即使未被使用. 通过绝对路径被引用,即以 / 开头的路径. 2.以

  • vue cli构建的项目中请求代理与项目打包问题

    在上篇文章给大家介绍了vue-cli webpack模板项目搭建及打包时路径问题的解决方法,可以点击查看. vue-cli构建的项目中,生产模式下的打包路径.与生产模式下的请求代理简单示意 总结 以上所述是小编给大家介绍的vue cli构建的项目中请求代理与项目打包问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的.在此也非常感谢大家对我们网站的支持! 您可能感兴趣的文章: Vue-cli创建项目从单页面到多页面的方法 Vue使用vue-cli创建项目 vue-cli项

  • 在vue-cli搭建的项目中增加后台mock接口的方法

    用vue-cli搭建一个前端开发环境确实是极其方便,在写前端代码肯定也是少不了需要调用后台提供的业务接口进行前后端交互,特别在敏捷开发中,前后端都要提前确定业务接口并进行打桩,在开发过程中基本是没有现成的后台可以调用,基本上都是自己写mock进行模拟. 在vue-cli搭建的项目中,框架上用的是express的web框架,要做一个mock是很方便的. 假设前端页面上需要获取所有的新闻列表,那么就需要mock一个能够返回所有新闻列表数据的接口. 接下来就在项目中实现mock功能. 脚手架生成项目

  • 详解vite+ts快速搭建vue3项目以及介绍相关特性

    vite 尤大在 Vue 3.0 beta 直播中推荐了 vite 的工具,强调:针对Vue单页面组件的无打包开发服务器,可以直接在浏览器运行请求的 vue 文件 很新颖,这篇博客用它来搭建一个 vue3 的项目试试 Vite 是面向现代浏览器,基于原生模块系统 ESModule 实现了按需编译的 Web 开发构建工具.在生产环境下基于 Rollup 打包 快速冷启动服务器 即时热模块更换(HMR) 真正的按需编译 node >= 10.16.0 搭建 使用 vite 搭建项目 npm init

  • react项目中@路径简单配置指南

    目录 前言 1. 安装craco 2.根路径下创建 craco.config.js 3. 修改package.json文件的script字段 4.使用 补充:React 配置 @ 路径别名 总结 前言 无论是vue还是react开发,我们通常需要引入路径的便捷化配置,通常我们都会约定使用路径@作为根路径地址.如果是个人react开发的@路径简单配置 1. 安装craco yarn add @craco/craco 2.根路径下创建 craco.config.js const path = req

  • vue和小程序项目中使用iconfont的方法

    一.vue中使用iconfont 1.百度搜索iconfont或者阿里巴巴矢量图标库官网,注册登录: 2.找到图标管理->新建项目,或者使用已有的项目,用于保存自己的图标: 3.搜索自己需要的icon: 4.添加到购物车中: 5.购物车中就有了相应icon 6.点击购物车,选择添加至项目.就是我们刚才创建的项目或者之前已有的项目 7.点击确定,即可将icon添加到我们的项目中 8.然后点击我的项目,找到自己的项目,即可看到刚才添加的icon 9.点击下载至本地 10.将下载的压缩包进行解压 11

  • Vue.js + Nuxt.js 项目中使用 Vee-validate 表单校验

    vee-validate 是为 Vue.js 量身打造的表单校验框架,允许您校验输入的内容并显示对应的错误提示信息.它内置了很多常见的校验规则,可以组合使用多种校验规则,大部分场景只需要配置就能实现开箱即用,还支持自定义正则表达式.而且支持 40 多种语言,对本地化.多语言支持非常友好. 国内饿了么团队开源项目 Element UI 就用到了 vee-validate . vee-validate 官网:https://baianat.github.io/vee-validate/ 1. 安装

  • idea2019导入maven项目中的某些问题及解决方法

    idea2019导入maven项目中的某些问题 idea2019导入maven项目,会出现很多莫名其妙的问题,需要注意的是如果是idea2019的版本是3月以前的,那会maven需要下载3.6.1以前版本,3.6.2版本不兼容 需要3.6.1版本的童鞋可在官网下载,或者用下面链接获取: 链接: https://pan.baidu.com/s/1nkJNF1OUuzHxgsBHXa5gow 提取码: snk3 配置maven的setting.xml文件 如果导入依赖出现问题时,可从以下几方面查看:

  • 用Vue-cli搭建的项目中引入css报错的原因分析

    我最近在研究Vue的路上,今天遇到了个问题,在vue cli 引入css报错,后来查询了很多资料,那么今天也算个学习笔记吧! 1.问题描述 之前用vue-cli搭建的项目,在main.js中引入elementUI库中的css,或者在其他文件中(比如App.vue)引入自己的css文件(假如你的文件是在src目录下),都会报一个相同的错.下如图 经过一番折腾之后发现需要在build文件下的webpack.base.conf.js中加上下面的代码即可 { test: /\.css$/, includ

  • mui-player自定义底部导航在vue项目中显示不出来的解决

    目录 mui-player自定义底部导航在vue项目中显示不出 效果图 总结 mui-player自定义底部导航在vue项目中显示不出 看了作者的源码和案例等,先上代码: <template> <div class="content-box"> <div class="container"> <div>视频插件 mui-player</div> <div id="mui-player&quo

随机推荐