zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    数据对象映射模式
    策略模式
    适配模式
    注册模式
    单例模式
    工厂模式
    PHP魔法方法的使用
    【转】通过 ulimit 改善系统性能
    HDMI相关知识
    中国三种3G网络频段
  • 原文地址:https://www.cnblogs.com/vickylinj/p/15599154.html
Copyright © 2011-2022 走看看