TaikiTkwkbysh
@TaikiTkwkbysh (WAKA Engineer)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

【Javascript】history.pushStateは「file:///...」でHTMLを開いた場合は機能しないのでしょうか。

■解決したいこと

タイトルの通りなのですが、
Javascriptをローカルホスト等も利用せず、 HTMLファイルを直接ブラウザにドラックして開いた場合(リンク:file:///...)は、pushStateを利用しても機能しないのでしょうか。

メソッドを実行してもエラーが出てしまい、履歴が更新されません。

■実行ソースファイル

ブラウザ上にあるボタンをクリックしたら、カウント数が上がるものです。

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="button" id="btn"value="カウントアップ">
    <span id="result">-</span>回クリックされました。
    <script src="main.js"></script>
</body>
</html>

Javascript

'use strict'

let count = 0;
let result = document.getElementById("result");

document.getElementById("btn").addEventListener("click",()=> {
    result.textContent = ++count;
    history.pushState(count, null, '/js/chap07/count/' + count);
});

window.addEventListener('popstate', function() {
    count = e.state;
    result.textContent = count;
})

■エラー内容追記

main.js:8 Uncaught DOMException: 
Failed to execute 'pushState' on 'History': 
A history state object with URL 'file:///js/chap07/count/1' 
cannot be created in a document with origin 'null' and URL 
'file:///Users/~/Desktop/~/index.html'.
    at HTMLInputElement.<anonymous> (file:///Users/~/Desktop/~/main.js:8:13)
0

3Answer

この問題は「同一オリジンポリシー」という仕組みに関連します。

現代的なブラウザは、スクリプトの読み込み元(=オリジン)が同一でないと、リソース(スクリプトやストレージ)を共有できないよう制限しています。

同一オリジンポリシーが機能しないと、代表的には以下の攻撃が可能になります。

  • クロスサイトリクエストフォージェリ(CSRF)攻撃

CSRF攻撃はクッキーやセッションなどのログイン状態の共有を悪用します。

file:///プロトコルのオリジンがどのように扱われるかは、htmlの仕様書には明記されていません。それぞれのブラウザがどのように扱うかを決めています。

ファイルオリジン
最近のブラウザは通常、file:/// スキーマを使用して読み込まれたファイルのオリジンを不透明なオリジンとして扱います。これは、例えばファイルに同じフォルダーからの他のファイルが含まれている場合、それらのファイルは同じ起源から来たとは見なされず、CORS エラーが発生する可能性があることを意味します。

現代的ブラウザでは、file:///でのアクセスを非常に厳しく管理します。file:///で読み出されたファイルは全て「不透明なオリジン」から読み出されたと扱われます。「不透明なオリジン」同士は同一のオリジンと見做されません。したがって同一ディレクトリー内のファイルの読み込みも異なるオリジンからの読み込みと同じ扱いになり制限されます。

以上の経緯から、外部スクリプトファイルを読み込み、期待通りに動作させるにはローカルサーバーを立ち上げるのが最も簡単な方法となります。例えばVSCodeの場合、LiveServerエクステンションを使うと、ワンクリックでローカルサーバーが立ち上がります。

参考記事

4Like

Comments

  1. @TaikiTkwkbysh

    Questioner

    @masato_makino様

    返信が遅くなってしまい、大変申し訳ございません。
    (自分が体調を崩してしまい、返答ができる状況にございませんでした。)

    この度はご教示いただき、誠にありがとうございます。
    やはりローカルサーバー等を立ち上げないといけないのですね。

    >>同一オリジンポリシー
    こちらの情報、大変助かります。
    全く存じておりませんでした...。

    VScodeを使用しているので、早速立ち上げて確認してみようとおもいます。

    この度はご対応頂き、ありがとうございました!
    また機会がございましたら、ぜひご教示頂けますと幸いです。

    以上、よろしくお願いいたします。

エラーでググると「できない」と出てきます。モダンブラウザではドメインが必要なみたいですね。

英語でも頑張って調べましょう、ページ翻訳すれば読める程度の優しさです。

2Like

Comments

  1. 一応伝えておきますと、クロスオリジン系のセキュリティの都合のようでセキュリティ切れば動く的なことが書いてはあります。
    なので検証用ならできなくは無いようですが、localhostでいいから何かしらのサーバーを立てたほうが良いと思います。
  2. @TaikiTkwkbysh

    Questioner

    @tonberry1050様
    返信が遅くなってしまい、大変申し訳ございません。
    (自分が体調を崩してしまい、返信ができる状況にございませんでした。)

    やはりそうだったのですね。stackoverflowのサイトも探してみたのですが、
    ご共有いただいたサイトに辿り着くことができませんでした...

    ご共有いただき、大変助かります!
    この度はご教示いただき、ありがとうございました。
    また機会がございましたら、ご教示いただけますと幸いです。

    以上、よろしくお願い致します。

メソッドを実行してもエラーが出てしまい、履歴が更新されません。

どんなエラーなんでしょう?

1Like

Comments

  1. @TaikiTkwkbysh

    Questioner

    @YumaInaura様

    コメントいただき、誠にありがとうございます。
    先ほど投稿欄にエラーログを追記いたしました。

    お手数お掛け致しますがご確認いただき、ご教示いただけますと幸いです。

    以上、よろしくお願い致します。

Your answer might help someone💌