14
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

株式会社D2C IDAdvent Calendar 2022

Day 17

vite でアセットを相対パスにする

Posted at

vite で開発/本番環境でアセットを相対パスにしようとしたら、
思ったよりてこずってしまったのでその忘備録です。

一番シンプルなパターン

アセットを相対パスで記述する最も簡単なパターンは、vite.config.js に下記の設定を追加することです。

vite.config.js
import { defineConfig } from 'vite'

export default defineConfig({
  base: "./"
})
style.scss
.box {
    background-image: url('/bg.png');
}

↓ ビルド後

style.css
.box {
    background-image: url('../bg.png');
}

ただ、この設定でも相対パスにならないケースがありました。

相対パスにならないケース

エントリーポイントを持たず、ビルドするファイルを rollupOptions で指定しているケース。
下記のように設定を行っている場合です。

vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
  build: {
    outDir: 'dist/assets',
    rollupOptions: {
      input: '/src/script/main.js',
      output: {
        entryFileNames: 'script/main.js',
        assetFileNames: `style/style.css`,
      }
    }
  }
})

このようなケースでは、ファイルのみが生成され、
読み込むアセットは HTML 側で指定することになります。
そのため、読み込むパスを相対で記述すればおおよそ問題ないのですが、
CSS の background-image の url() などが絶対パスのまま残ってしまいます。

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>title</title>
    <link rel="stylesheet" href="./assets/css/style.css">
  </head>
  <body>
    <div class="box"></div>
    <script src="./assets/script/main.ts"></script>
  </body>
</html>
style.css
.box {
    background-image: url('/assets/images/bg.png'); /* 絶対パスのまま */
}

CSS の url() を相対パスで記述したときの問題

CSS 内の url() を相対パスで記述すれば、パス自体は相対パスのまま出力されます。
しかし、上記の出力設定のままだと CSS の出力が開発中とビルドで異なるという問題が発生します。

具体的には、

  • 開発中の CSS は <style> タグに変換され <head> 内に挿入される
  • ビルド時の CSS は指定したディレクトリにファイルとして書き出される

そのため、url() を相対パスで記述すると開発中とビルド時で参照がずれることがあります。

vite(rollup)ビルドのオプションで url() のパスを書き換える

この対策として、vite(rollup)ビルドのオプションで書き換えを行いました。
使うのは、additionalData オプションです。

vite.dev.config.js
import { defineConfig } from 'vite'
export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `$base-dir: '/assets/';`,
      },
    },
  }, 
})
vite.build.config.js
import { defineConfig } from 'vite'
export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `$base-dir: '../';`,
      },
    },
  }, 
})

開発用、ビルド用で vite.config.js を2種類用意しました。
これで、scss に $base-dir という変数を渡すことができるので、
scss 側で変数を使って url() を指定します。

style.scss
.box {
  $src: $base-dir + 'images/bg.png';
  background-image: url($src);
}

力技になってしまったのですが、この手法で vite のアセットを相対パスにすることができました。
他にもっとスマートな方法がある気もするのですが。。
良い方法をご存知でしたら、コメントなどからご教示いただけますと幸いです:bow:

14
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?