From 4413dd3ba4e588f539d1e49e1abc0278538d2de6 Mon Sep 17 00:00:00 2001 From: F-Makoto <129283674+F-Makoto@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:40:02 +0900 Subject: [PATCH 01/28] Update index.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit non-negative の訳を「非負」に修正しました。 --- files/ja/web/html/element/meta/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/ja/web/html/element/meta/index.md b/files/ja/web/html/element/meta/index.md index 1bbd2de3d8a9d8..ebbb267fe6869a 100644 --- a/files/ja/web/html/element/meta/index.md +++ b/files/ja/web/html/element/meta/index.md @@ -119,8 +119,8 @@ l10n: - `refresh` これは以下のことを指定する指示です。 - - [`content`](#content) 属性に正の整数が 1 つだけ含まれている場合は、ページを再読み込みするまでの秒数。 - - [`content`](#content) 属性に正の整数と、その後に文字列 '`;url=`' と有効な URL がある場合は、別のページにリダイレクトするまでの秒数。 + - [`content`](#content) 属性に非負の整数が 1 つだけ含まれている場合は、ページを再読み込みするまでの秒数。 + - [`content`](#content) 属性に非負の整数と、その後に文字列 '`;url=`' と有効な URL がある場合は、別のページにリダイレクトするまでの秒数。 > [!WARNING] > From 4e05caa5a838c7c18327e0860dddf0f5ecaa8349 Mon Sep 17 00:00:00 2001 From: A1lo Date: Fri, 16 Aug 2024 10:39:16 +0800 Subject: [PATCH 02/28] zh-cn: update the translation of `HTMLFormElement` (#22912) Co-authored-by: Jason Ren <40999116+jasonren0403@users.noreply.github.com> --- files/zh-cn/web/api/htmlformelement/index.md | 361 ++++++++++--------- 1 file changed, 185 insertions(+), 176 deletions(-) diff --git a/files/zh-cn/web/api/htmlformelement/index.md b/files/zh-cn/web/api/htmlformelement/index.md index 4ac36567e2b579..7855b63f6dc018 100644 --- a/files/zh-cn/web/api/htmlformelement/index.md +++ b/files/zh-cn/web/api/htmlformelement/index.md @@ -1,232 +1,241 @@ --- title: HTMLFormElement slug: Web/API/HTMLFormElement +l10n: + sourceCommit: c99afd3cafe73c93831bd73ad1dac285c3c713b1 --- {{APIRef("HTML DOM")}} -HTMLFormElement 接口可以创建或者修改{{HTMLElement("form")}}对象;它继承了{{domxref("HTMLElement")}}接口的方法和属性。 +**`HTMLFormElement`** 接口表示 DOM 中的 {{HTMLElement("form")}} 元素。它允许访问和(在某些情况下)修改表单的各个方面,以及访问其组成元素。 -## 属性 +{{InheritanceDiagram}} -_继承自父类的属性,{{domxref("HTMLElement")}}._ +## 实例属性 -- {{domxref("HTMLFormElement.acceptCharset")}} - - : Is a {{domxref("DOMString")}} that reflects the [`accept-charset`](/zh-CN/docs/Web/HTML/Element/form#accept-charset) HTML attribute, containing a list of character encodings that the server accepts. +_此接口还从其父接口 {{domxref("HTMLElement")}} 继承属性。_ + +- {{domxref("HTMLFormElement.elements")}} {{ReadOnlyInline}} + - : 包含所有属于此表单元素的表单控件的 {{domxref("HTMLFormControlsCollection")}}。 +- {{domxref("HTMLFormElement.length")}} {{ReadOnlyInline}} + - : 反映表单中控件的数量的 `long` 值。 +- {{domxref("HTMLFormElement.name")}} + - : 反映表单的 [`name`](/zh-CN/docs/Web/HTML/Element/form#name) HTML 属性值的字符串,包含表单的名称。 +- {{domxref("HTMLFormElement.method")}} + - : 反映表单的 [`method`](/zh-CN/docs/Web/HTML/Element/form#method) HTML 属性值的字符串,表示用于提交表单的 HTTP 方法。只能设置特定的值。 +- {{domxref("HTMLFormElement.target")}} + - : 反映表单的 [`target`](/zh-CN/docs/Web/HTML/Element/form#target) HTML 属性值的字符串,表示用于显示提交表单的结果的位置。 - {{domxref("HTMLFormElement.action")}} - - : Is a {{domxref("DOMString")}} that reflects the [`action`](/zh-CN/docs/Web/HTML/Element/form#action) HTML attribute, containing the URI of a program that processes the information submitted by the form. + - : 反映表单的 [`action`](/zh-CN/docs/Web/HTML/Element/form#action) HTML 属性值的字符串,包含处理表单提交的信息的程序的 URI。 +- {{domxref("HTMLFormElement.encoding")}} 或 {{domxref("HTMLFormElement.enctype")}} + - : 反映表单的 [`enctype`](/zh-CN/docs/Web/HTML/Element/form#enctype) HTML 属性值的字符串,表示用于将表单传输到服务器的内容类型。只能设置特定的值。这两个属性是同义词。 +- {{domxref("HTMLFormElement.acceptCharset")}} + - : 反映表单的 [`accept-charset`](/zh-CN/docs/Web/HTML/Element/form#accept-charset) HTML 属性值的字符串,表示服务器接受的字符编码。 - {{domxref("HTMLFormElement.autocomplete")}} - - : Is a {{domxref("DOMString")}} that reflects the [`autocomplete`](/zh-CN/docs/Web/HTML/Element/form#autocomplete) HTML attribute, containing a string that indicates whether the controls in this form can have their values automatically populated by the browser. -- {{domxref("HTMLFormElement.elements")}} {{readonlyinline}} - - : Returns a live {{domxref("HTMLFormControlsCollection")}} containing all the form controls belonging to this form element. -- {{domxref("HTMLFormElement.encoding")}} - - : Is a synonym for `enctype`. -- {{domxref("HTMLFormElement.enctype")}} - - : Is a {{domxref("DOMString")}} reflects the [`enctype`](/zh-CN/docs/Web/HTML/Element/form#enctype) HTML attribute, indicating the type of content that is used to transmit the form to the server. Only specified values can be set. -- {{domxref("HTMLFormElement.length")}} {{readonlyinline}} - - : Returns a `long` that represents the number of controls in the form. -- {{domxref("HTMLFormElement.method")}} - - : Is a {{domxref("DOMString")}} that reflects the [`method`](/zh-CN/docs/Web/HTML/Element/form#method) HTML attribute, indicating the HTTP method used to submit the form. Only specified values can be set. -- {{domxref("HTMLFormElement.name")}} - - : Is a {{domxref("DOMString")}} that reflects the [`name`](/zh-CN/docs/Web/HTML/Element/form#name) HTML attribute, containing the name of the form. + - : 反映表单的 [`autocomplete`](/zh-CN/docs/Web/HTML/Element/form#autocomplete) HTML 属性值的字符串,表示此表单中的控件是否可以由浏览器自动填充其值。 - {{domxref("HTMLFormElement.noValidate")}} - - : Is a {{jsxref("Boolean")}} that reflects the [`novalidate`](/zh-CN/docs/Web/HTML/Element/form#novalidate) HTML attribute, indicating that the form should not be validated. -- {{domxref("HTMLFormElement.target")}} - - : Is a {{domxref("DOMString")}} that reflects the [`target`](/zh-CN/docs/Web/HTML/Element/form#target) HTML attribute, indicating where to display the results received from submitting the form. + - : 反映表单的 [`novalidate`](/zh-CN/docs/Web/HTML/Element/form#novalidate) HTML 属性值的布尔值,表示是否不应对表单进行验证。 -## 方法 +具名输入会被作为属性添加到其所属表单的实例中,且如果它们共享相同的名称(例如,具有名为 `action` 的输入的表单将使其 `action` 属性返回该输入,而不是表单的 [`action`](/zh-CN/docs/Web/HTML/Element/form#action) HTML 属性)。 -_这个元素继承了 {{domxref("HTMLElement")}} 的属性。_ +## 实例方法 -- {{domxref("HTMLFormElement.checkValidity()")}} - - : Returns a {{jsxref("Boolean")}} that is `true` if the element's child controls are subject to constraint validation and satify those contraints, or `false` if some controls do not satisfy their constraints. Fires an event named [`invalid`](/zh-CN/docs/Web/API/HTMLInputElement/invalid_event) at any control that does not satisfy its constraints; such controls are considered invalid if the event is not canceled. It is up to the programmer to decide how to respond to `false`. -- {{domxref("HTMLFormElement.item()")}} - - : Gets the item in the `elements` collection at the specified index, or null if there is no item at that index. You can also specify the index in array-style brackets or parentheses after the form object name, without calling this method explicitly. -- {{domxref("HTMLFormElement.namedItem()")}} - - : 从元素集合中获取 `name` 或者 `id` 与指定名称匹配的项,没有匹配项则返回 null。你也可以像调用数组那样用圆括号或方括号来指定名称,而不必显式地调用这个方法。 -- {{domxref("HTMLFormElement.submit()")}} - - : Submits the form to the server. -- {{domxref("HTMLFormElement.reset()")}} - - : Resets the forms to its initial state. -- {{domxref("HTMLFormElement.reportValidity()")}} - - : Returns `true` if the element's child controls satisfy their validation constraints. When `false` is returned, cancelable [`invalid`](/zh-CN/docs/Web/Events/invalid) events are fired for each invalid child and validation problems are reported to the user. +_此接口还从其父接口 {{domxref("HTMLElement")}} 继承方法。_ -## Examples +- {{domxref("HTMLFormElement.checkValidity", "checkValidity()")}} + - : 如果元素的子控件受到[约束验证](/zh-CN/docs/Web/HTML/Constraint_validation)并满足这些约束,则返回 `true`;如果某些控件不满足其约束,则返回 `false`。在不满足其约束的任何控件上触发名为 {{domxref("HTMLInputElement/invalid_event", "invalid")}} 的事件;如果未取消事件,则这些控件被视为无效。由程序员决定如何响应 `false`。 +- {{domxref("HTMLFormElement.reportValidity", "reportValidity()")}} + - : 如果元素的子控件满足其[验证约束](/zh-CN/docs/Web/HTML/Constraint_validation),则返回 `true`。当返回 `false` 时,将为每个无效的子控件触发可取消的 {{domxref("HTMLInputElement/invalid_event", "invalid")}} 事件,并将验证问题报告给用户。 +- {{domxref("HTMLFormElement.requestSubmit", "requestSubmit()")}} + - : 请求使用指定的提交按钮及其相应的配置来提交表单。 +- {{domxref("HTMLFormElement.reset", "reset()")}} + - : 将表单重置为其初始状态。 +- {{domxref("HTMLFormElement.submit", "submit()")}} + - : 将表单提交至服务器。 -The following example shows how to create a new form element, modify its attributes and submit it. +## 事件 -```js -// Create a form -var f = document.createElement("form"); +使用 `addEventListener()` 或将事件监听器赋值给此接口的 `oneventname` 属性来监听这些事件。 -// Add it to the document body -document.body.appendChild(f); +- {{domxref("HTMLFormElement/formdata_event", "formdata")}} + - : 在构建表示表单数据的条目列表之后触发 `formdata` 事件。 +- {{domxref("HTMLFormElement/reset_event", "reset")}} + - : 在表单重置时触发 `reset` 事件。 +- {{domxref("HTMLFormElement/submit_event", "submit")}} + - : 在表单提交时触发 `submit` 事件。 -// Add action and method attributes -f.action = "/cgi-bin/some.cgi"; -f.method = "POST"; +## 使用说明 + +### 获得表单元素对象 + +要获取 `HTMLFormElement` 对象,你可以使用 [CSS 选择器](/zh-CN/docs/Web/CSS/CSS_selectors)和 {{domxref("Document.querySelector", "querySelector()")}},或者使用文档的 {{domxref("Document.forms", "forms")}} 属性获取文档中所有表单的列表。 + +{{domxref("Document.forms")}} 返回 `HTMLFormElement` 对象数组,其中列出了页面上的每个表单。然后,你可以使用以下任何语法来获取单个表单: + +- `document.forms[index]` + - : 返回数组中指定索引(`index`)的表单。 +- `document.forms[id]` + - : 返回 ID 为 `id` 的表单。 +- `document.forms[name]` + - : 返回 `name` 属性值为 `name` 的表单。 + +### 访问表单的元素 + +你可以通过检查表单的 {{domxref("HTMLFormElement.elements", "elements")}} 属性来访问表单中用于包含数据的元素列表。这将返回一个 {{domxref("HTMLFormControlsCollection")}},其中列出了表单的所有用户数据输入元素,包括 `
` 的后代元素,以及使用其 `form` 属性而成为表单成员的元素。 + +你也可以通过将表单元素 `name` 属性作为 `form` 的键来获取该表单的元素,但使用 `elements` 是一个更好的方法——它*只*包含表单的元素,并且不能与 `form` 的其他属性混合使用。 + +### 元素命名问题 + +有些名称会干扰 JavaScript 访问表单的属性和元素。 + +例如: + +- `` 会优先于 ``。这意味着 `form.id` 不会引用表单的 id,而是引用名称为“`id`”的元素。这也适用于其他表单属性,例如 `` 或 ``。 +- `` 会使表单的 `elements` 集合无法访问。引用 `form.elements` 现在将引用单个元素。 + +要避免这些元素名称的问题,你应该: + +- *始终*使用 `elements` 集合来避免元素名称和表单属性之间的歧义。 +- *切勿*将“`elements`”作为元素名称。 + +如果你不使用 JavaScript,这不会造成问题。 + +### 被视为表单控件的元素 -// Call the form's submit method -f.submit(); +`HTMLFormElement.elements` 和 `HTMLFormElement.length` 包含以下元素: + +- {{HTMLElement("button")}} +- {{HTMLElement("fieldset")}} +- {{HTMLElement("input")}}(但由于历史原因,[`type`](/zh-CN/docs/Web/HTML/Element/input#type) 为 `"image"` 的元素会被忽略) +- {{HTMLElement("object")}} +- {{HTMLElement("output")}} +- {{HTMLElement("select")}} +- {{HTMLElement("textarea")}} + +`elements` 返回的列表不包含其他元素,这使得它成为处理表单时获取最重要元素的绝佳方法。 + +## 示例 + +创建一个新的表单元素,修改其属性,然后提交: + +```js +const f = document.createElement("form"); // 创建表单 +document.body.appendChild(f); // 将其添加到文档主体 +f.action = "/cgi-bin/some.cgi"; // 添加 action 和 method 属性 +f.method = "POST"; +f.submit(); // 调用表单的 submit() 方法 ``` -In addition, the following complete HTML document shows how to extract information from a form element and to set some of its attributes. +从 `` 元素中提取信息并设置一些属性: ```html -Form example - - -

Form example

- - -

- Click "Info" to see information about the form. Click set to change - settings, then info again to see their effect -

-

- - - -
- -

-
``` -The following example shows how to submit a form in a [popup window](/zh-CN/docs/DOM/window.open). +在新窗口中提交表单(`
`): ```html - + - - MDN Example - + + 在新窗口提交表单的示例 - - + +

+ +

- First name:
- Last name:
- Password:
- Male - Female +

- I have a bike
- I have a car +

-

+ +
+ 宠物偏好 + +

+ +

+

+ +

+
+ +
+ 拥有的车辆 + +

+ +

+

+ +

+
+ +

``` -### Submitting forms and uploading files using `XMLHttpRequest` - -If you want to know how to serialize and submit a form using the [`XMLHttpRequest`](/zh-CN/docs/DOM/XMLHttpRequest) API, please read [this paragraph](/zh-CN/docs/DOM/XMLHttpRequest_API/Using_XMLHttpRequest#Submitting_forms_and_uploading_files). - -## Specifications +## 规范 {{Specifications}} -## Browser compatibility +## 浏览器兼容性 {{Compat}} -## See also +## 参见 -- The HTML element implementing this interface: {{ HTMLElement("form") }}. +- 实现此接口的 HTML 元素:{{HTMLElement("form")}}。 From b02acbc0b66cbdfad69d9ba3c6a9ffa539a9a11d Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 12 Aug 2024 16:16:43 +0900 Subject: [PATCH 03/28] =?UTF-8?q?2024/07/26=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=96=B0=E8=A6=8F=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../offline_and_background_operation/index.md | 453 ++++++++++++++++++ .../push-messaging-1.svg | 1 + .../push-messaging-2.svg | 1 + 3 files changed, 455 insertions(+) create mode 100644 files/ja/web/progressive_web_apps/guides/offline_and_background_operation/index.md create mode 100644 files/ja/web/progressive_web_apps/guides/offline_and_background_operation/push-messaging-1.svg create mode 100644 files/ja/web/progressive_web_apps/guides/offline_and_background_operation/push-messaging-2.svg diff --git a/files/ja/web/progressive_web_apps/guides/offline_and_background_operation/index.md b/files/ja/web/progressive_web_apps/guides/offline_and_background_operation/index.md new file mode 100644 index 00000000000000..81a7663df2001c --- /dev/null +++ b/files/ja/web/progressive_web_apps/guides/offline_and_background_operation/index.md @@ -0,0 +1,453 @@ +--- +title: オフライン操作とバックグラウンド処理 +slug: Web/Progressive_web_apps/Guides/Offline_and_background_operation +l10n: + sourceCommit: 857c6f9e7f1a847e7d3466b0d047159f7b345991 +--- + +{{PWASidebar}} + +通常、ウェブサイトは信頼性の高いネットワーク接続と、ユーザーがブラウザーでページを開いていることの両方に強く依存しています。ネットワーク接続がなければ、ほとんどのウェブサイトは利用できませんし、ユーザーがブラウザータブでサイトを開いていない場合、ほとんどのウェブサイトは何もできません。 + +しかし、以下のシナリオを考えてみてください。 + +- 音楽アプリでは、ユーザーはオンライン中に音楽をストリーミングすることができますが、バックグラウンドで曲をダウンロードし、ユーザーがオフラインの間も再生し続けることができます。 +- ユーザーが長い電子メールを作成し、「送信」を押した後、ネットワーク接続が切断されたとします。ネットワークが再び利用できるようになると、端末がバックグラウンドでメールを送信します。 +- ユーザーのチャットアプリが連絡先の1人からメッセージを受信したとき、アプリが開いていないにもかかわらず、アプリアイコンにバッジが表示され、新しいメッセージがあることをユーザーに知らせます。 + +これらはユーザーがインストール型アプリに期待する機能です。このガイドでは、PWA を実現する設定するにはどのような技術が必要かを紹介します。 + +- 端末のネットワーク接続が断続的な場合でも、よい使い勝手で利用できる +- アプリが実行されていないときに状態を更新する +- アプリが実行されていない間に起こった重要なイベントをユーザーに通知する + +このガイドで紹介する技術は以下の通りです。 + +- [サービスワーカー API](/ja/docs/Web/API/Service_Worker_API) +- [バックグラウンド同期 API](/ja/docs/Web/API/Background_Synchronization_API) +- [バックグラウンドフェッチ API](/ja/docs/Web/API/Background_Fetch_API) +- [定期的バックグラウンド同期 API](/ja/docs/Web/API/Web_Periodic_Background_Synchronization_API) +- [プッシュ API](/ja/docs/Web/API/Push_API) +- [通知 API](/ja/docs/Web/API/Notifications_API) + +## ウェブサイトとワーカー + +このガイドで説明するすべての技術の基礎となるのが _service worker_ です。この章ではワーカーの背景と、ワーカーがウェブアプリのアーキテクチャをどのように変えるのかについて少し説明します。 + +通常、ウェブサイト全体は単一のスレッドで実行します。これにはウェブサイト自身の JavaScript や、ウェブサイトの UI をレンダリングするためのすべての作業が含まれます。この結果、JavaScript が長時間実行する処理を実行すると、ウェブサイトのメイン UI がブロックされ、ウェブサイトがユーザーに対して無反応に見えます。 + +[サービスワーカー](/ja/docs/Web/API/Service_Worker_API)は、PWA を実装するために用いる特定の種類の[ウェブワーカー](/ja/docs/Web/API/Web_Workers_API)です。すべてのウェブワーカーのように、サービスワーカーはメイン JavaScript コードとは別のスレッドで実行します。メインコードでワーカーを作成し、ワーカーのスクリプトに URL を渡します。ワーカーとメインコードは直接お互いの状態にアクセスすることはできませんが、メッセージを送り合うことで通信することができます。ワーカーは別のスレッドで実行されるため、アプリの UI を実装するアプリのメイン JavaScript コードはユーザーに対して応答し続けることができます。 + +そのため、PWA は常に高水準のアーキテクチャを 2 つに分けて持っています。 + +- メインアプリ。HTML、CSS と、アプリの UI を実装する JavaScript の一部(例えばユーザーイベントの処理)。 +- オフラインとバックグラウンドのタスクを処理するサービスワーカー。 + +このガイドでは、コードサンプルを表示させるとき、そのコードがアプリのどの部分に属するかを `// main.js` や `// service-worker.js` のようなコメントで示します。 + +## オフライン操作 + +オフライン操作は、端末にネットワーク接続がない場合でも PWA が良い使い勝手を提供することができます。これはアプリにサービスワーカーを追加することで可能になります。 + +サービスワーカーはアプリの一部またはすべてのページを制御します。サービスワーカーがインストールされると、制御するページのリソース(例えばページ、スタイル設定、スクリプト、画像など)をサーバーから取得し、ローカルキャッシュに追加することができます。リソースをキャッシュに追加するには {{domxref("Cache")}} インターフェイスを使用します。`Cache` インスタンスには、サービスワーカーのグローバルスコープの {{domxref("WorkerGlobalScope.caches")}} プロパティからアクセスします。 + +そして、アプリがリソースをリクエストするたびに(例えば、ユーザーがアプリを開いたり、内部リンクをクリックしたりしたために)、ブラウザーはサービスワーカーのグローバルスコープで{{domxref("ServiceWorkerGlobalScope.fetch_event", " fetch")}}というイベントを呼び出します。このイベントを待ち受けすることで、サービスワーカーはリクエストを介入することができます。 + +`fetch` イベントのイベントハンドラーには、次の機能を持つ {{domxref("FetchEvent")}} オブジェクトが渡されます。 + +- リクエストへの {{domxref("Request")}} インスタンスとしてのアクセスを提供します。 +- リクエストに対するレスポンスを送信する {{domxref("FetchEvent.respondWith", "respondWith()")}} メソッドを提供します。 + +サービスワーカーがリクエストを処理する方法の一つは、「キャッシュ優先」戦略です。この戦略では、 + +1. リクエストされたリソースがキャッシュに存在する場合、キャッシュからリソースを取得し、アプリにリソースを返します。 +2. リクエストされたリソースがキャッシュに存在しない場合は、ネットワークからリソースを取得しようとします。 + 1. リソースが取得できた場合は、次回のためにリソースをキャッシュに追加し、アプリにリソースを返します。 + 2. リソースを取得できなかった場合は、既定の代替リソースを返します。 + +以下のコードサンプルは、この実装を示しています。 + +```js +// service-worker.js + +const putInCache = async (request, response) => { + const cache = await caches.open("v1"); + await cache.put(request, response); +}; + +const cacheFirst = async ({ request, fallbackUrl }) => { + // 最初にキャッシュからリソースを取得しようとする。 + const responseFromCache = await caches.match(request); + if (responseFromCache) { + return responseFromCache; + } + + // レスポンスがキャッシュ内で得られなかった場合は、 + // ネットワークからリソースを取得しようとする。 + try { + const responseFromNetwork = await fetch(request); + // ネットワークリクエストが成功した場合は、レスポンスを複製する + // - 次回のためにコピーをキャッシュに入れる + // - オリジナルをアプリに返す + // レスポンスは一度しか消費できないため、複製が必要。 + putInCache(request, responseFromNetwork.clone()); + return responseFromNetwork; + } catch (error) { + // ネットワークリクエストが失敗した場合は、 + // キャッシュから代替レスポンスを取得する。 + const fallbackResponse = await caches.match(fallbackUrl); + if (fallbackResponse) { + return fallbackResponse; + } + // 代替レスポンスすら利用できない場合はどうしようもないが、 + // 常に Response オブジェクトを返す必要がある。 + return new Response("ネットワークエラーが発生", { + status: 408, + headers: { "Content-Type": "text/plain" }, + }); + } +}; + +self.addEventListener("fetch", (event) => { + event.respondWith( + cacheFirst({ + request: event.request, + fallbackUrl: "/fallback.html", + }), + ); +}); +``` + +これは、多くの場合、ネットワーク接続が断続的であってもウェブアプリは正常に機能するということです。メインアプリのコードから見れば、完全に透明です。アプリはネットワークリクエストを行い、レスポンスを取得するだけです。また、サービスワーカは別のスレッドにあるため、リソースを取得してキャッシュしている間、メインアプリコードは常にユーザーの入力に応答し続けることができます。 + +> [!NOTE] +> ここで記述されている戦略は、サービスワーカーがキャッシュを実装する一つの方法に過ぎません。具体的には、キャッシュ優先戦略では、ネットワークの前にまずキャッシュを調べます。つまり、ネットワークコストをかけずに素早いレスポンスを返す可能性が高くなる一方で、古いレスポンスを返す可能性も高くなるということを意味しています。 +> +> 他の方法としては、ネットワーク優先戦略というものがあります。これは、最初にサーバーからリソースを取得し、端末がオフラインの場合はキャッシュで代替するというものです。 +> +> 最適なキャッシュ戦略は、具体的なウェブアプリと使用する方法によって異なります。 + +サービスワーカーを設定し、オフライン機能を追加するために使用する方法については、[サービスワーカーの使用](/ja/docs/Web/API/Service_Worker_API/Using_Service_Workers)ガイドをご覧ください。 + +## バックグラウンド処理 + +オフライン処理はサービスワーカーの最も一般的な使用方法ですが、メインアプリが閉じられている間でも PWA を動作させることができます。これはサービスワーカーがメインアプリが実行されていない間でも実行することができるため可能なことです。 + +これは、サービスワーカーが常に実行されているという意味ではありません。ブラウザーは、適切と思われるときにサービスワーカーを停止することがあります。例えば、サービスワーカーがしばらく活動していない場合、停止されます。しかし、ブラウザーはサービスワーカーに必要なイベントが発生すると、サービスワーカーを再起動します。これにより、PWA は以下の方法でバックグラウンド処理を実行することができます。 + +- メインアプリで、サービスワーカーに何らかの処理を運営するリクエストを登録します +- 適切なタイミングで、サービスワーカーは必要に応じて再起動され、サービスワーカーのスコープでイベントが発行されます +- サービスワーカが処理を行います + +次の節では、このパターンを使用して、メインアプリが開いていない間でも PWA が動作するようにするいくつかの異なる機能について説明します。 + +## バックグラウンド同期 + +ユーザーがメールを作成し、「送信」を押したとします。従来のウェブサイトでは、アプリがメールを送信するまでタブを開いたままにしておかなければなりません。タブを閉じたり、端末が接続できなくなったりすると、メールは送信されません。[バックグラウンド同期 API](/ja/docs/Web/API/Background_Synchronization_API) で定義するバックグラウンド同期は、PWA にとってこの問題の解決策です。 + +バックグラウンド同期により、アプリはサービスワーカーにタスクを代行するよう依頼することができます。端末がネットワーク接続を保有するとすぐに、ブラウザーは必要に応じてサービスワーカーを再起動し、サービスワーカーのスコープで [`sync`](/ja/docs/Web/API/ServiceWorkerGlobalScope/sync_event) という名前のイベントを発生します。サービスワーカーはタスクの実行を試みます。タスクが完了できない場合、ブラウザーは制限された回数だけイベントを再試行することができます。 + +### 同期イベントの登録 + +サービスワーカーにタスクの実行を依頼するには、メインアプリは {{domxref("ServiceWorkerContainer/ready", "navigator.serviceWorker.ready")}} にアクセスし、{{domxref("ServiceWorkerRegistration")}} オブジェクトで解決します。アプリは次に、次のように `ServiceWorkerRegistration` オブジェクトの {{domxref("SyncManager/register", "sync.register()")}} を呼び出します。 + +```js +// main.js + +async function registerSync() { + const swRegistration = await navigator.serviceWorker.ready; + swRegistration.sync.register("send-message"); +} +``` + +なお、このアプリはタスクの名前 `"send-message"` を渡しています。 + +### 同期イベントの処理 + +端末がネットワークに接続されるとすぐに、サービスワーカースコープで `sync` イベントが発生します。サービスワーカーはタスクの名前を調べ、適切な関数、この場合は `sendMessage()` を実行します。 + +```js +// service-worker.js + +self.addEventListener("sync", (event) => { + if (event.tag == "send-message") { + event.waitUntil(sendMessage()); + } +}); +``` + +`sendMessage()` 関数の結果をイベントの {{domxref("ExtendableEvent/waitUntil", "waitUntil()")}} メソッドに渡していることに注意してください。`waitUntil()` メソッドは {{jsxref("Promise")}} を引数に取り、プロミスが決定するまでサービスワーカーの停止をしないようブラウザーに要求します。これは、ブラウザーが処理が成功したかどうかを知る方法でもあります。プロミスが拒否された場合、ブラウザーは `sync` イベントを再度発行して再試行します。 + +`waitUntil()` メソッドはブラウザーがサービスワーカーを停止させないことを保証するものではありません。処理に時間がかかりすぎる場合、サービスワーカーはいずれにせよ停止されます。このような場合、処理は中止され、次に `sync` イベントが発生したときにハンドラーが最初から実行されます。 + +どのくらいの時間が「長すぎる」かはブラウザーに依存します。Chrome の場合、サービスワーカーは次のような場合に閉じられたと考えられます。 + +- 30 秒のアイドル状態が続いた場合 +- 同期 JavaScript を 30 秒間実行している場合 +- `waitUntil()` に渡されたプロミスが決定するまで 5 分以上かかっている場合 + +## バックグラウンドフェッチ + +バックグラウンド同期は比較的短時間のバックグラウンド処理に有益ですが、先ほど見たように、サービスワーカーが相対的に短時間で同期イベントの処理を完了しない場合、ブラウザーはサービスワーカーを停止します。これは、アプリがバックグラウンドにある間、ユーザーの IP アドレスがサーバーに公開される時間を最小限にすることで、バッテリー寿命を節約し、ユーザーのプライバシーを保護するための意図的な措置です。 + +このため、例えばムービーをダウンロードするような、長い処理を行うにはバックグラウンド同期は不向きです。このシナリオでは、[バックグラウンドフェッチ API](/ja/docs/Web/API/Background_Fetch_API) が必要です。バックグラウンドフェッチを使うと、メインアプリの UI とサービスワーカーの両方が閉じている間にネットワークリクエストを実行できます。 + +バックグラウンドフェッチでは、次のようになります。 + +- リクエストはメインアプリの UI から開始されます。 +- メインアプリが開いているかどうかに関わらず、ブラウザーは進行中のリクエストをユーザーに通知し、キャンセルされる可能性や進行状況を調べることを可能にする持続的な UI 要素を表示します。 +- リクエストが成功または失敗で完全に発行されるか、ユーザーがリクエストの進行状況を調べるよう依頼されると、ブラウザーはサービスワーカーを(必要であれば)開始し、サービスワーカーのスコープで適切なイベントを発行します。 + +### バックグラウンドフェッチリクエストの実行 + +バックグラウンドフェッチリクエストは、メインアプリのコードで次のように {{domxref("BackgroundFetchManager/fetch", "backgroundFetch.fetch()")}} を `ServiceWorkerRegistration` オブジェクトで呼び出すことで開始されます。 + +```js +// main.js + +async function requestBackgroundFetch(movieData) { + const swRegistration = await navigator.serviceWorker.ready; + const fetchRegistration = await swRegistration.backgroundFetch.fetch( + "download-movie", + ["/my-movie-part-1.webm", "/my-movie-part-2.webm"], + { + icons: movieIcons, + title: "Downloading my movie", + downloadTotal: 60 * 1024 * 1024, + }, + ); + //... +} +``` + +`backgroundFetch.fetch()` には次の 3 つの引数を渡しています。 + +1. このフェッチリクエストの識別子 +2. {{domxref("Request")}} オブジェクトまたは URL の配列。単一のバックグラウンドフェッチリクエストに複数のネットワークリクエストを含めることができます。 +3. リクエストの存在と進行状況を示すためにブラウザーが使用する UI のためのデータを格納するオブジェクト。 + +`backgroundFetch.fetch()` 呼び出しは {{domxref("BackgroundFetchRegistration")}} オブジェクトで解決する {{jsxref("Promise")}} を返します。これにより、リクエストの進行に合わせてメインアプリが自分自身で UI を更新できるようになります。しかし、メインアプリが閉じられた場合、フェッチはバックグラウンドで続けられます。 + +ブラウザーは、リクエストが進行中であることをユーザーに思い出させる持続的な UI 要素を表示し、リクエストの詳細を探したり、必要であれば取り消される可能性をユーザーに与えます。UI には `icons` と `title` 引数から取ったアイコンとタイトルが記載され、 `downloadTotal` を使用して総ダウンロードサイズを推定し、リクエストの進行状況を示します。 + +### リクエスト結果の処理 + +フェッチが成功または失敗で完了するか、ユーザーが進行状況UIをクリックすると、ブラウザーは必要に応じてアプリのサービスワーカーを開始し、サービスワーカーのスコープでイベントを発生させます。以下のイベントが発生します。 + +- `backgroundfetchsuccess`: すべてのリクエストが成功した場合 +- `backgroundfetchfail`: 1 つ以上のリクエストが失敗した場合 +- `backgroundfetchabort`: フェッチがユーザーまたはメインアプリによって中止された場合 +- `backgroundfetchclick`: ブラウザーが表示している進行状況の UI 要素をユーザーがクリックした場合 + +#### レスポンスデータの取得 + +`backgroundfetchsuccess`、`backgroundfetchfail`、`backgroundfetchabort` の各イベントのハンドラーで、サービスワーカーはリクエストデータとレスポンスデータを取得できます。 + +レスポンスを取得するには、イベントハンドラーはイベントの {{domxref("BackgroundFetchEvent/registration", "registration")}} プロパティにアクセスします。これは{{domxref("BackgroundFetchRegistration")}} オブジェクトには {{domxref("BackgroundFetchRegistration/matchAll", "matchAll()")}} と {{domxref("BackgroundFetchRegistration/match")}} メソッドがあり、指定された URL に一致する {{domxref("BackgroundFetchRecord")}} オブジェクトを返します(`matchAll()` の場合、指定された URL がない場合はすべてのレコードを返します)。 + +それぞれの `BackgroundFetchRecord` には {{domxref("BackgroundFetchRecord/responseReady", "responseReady")}} プロパティがあります。これはレスポンスが利用できるようになると {{domxref("Response")}} で解決する `Promise` です。 + +レスポンスデータにアクセスするには、ハンドラーは次のようにします。 + +```js +// service-worker.js + +self.addEventListener("backgroundfetchsuccess", (event) => { + const registration = event.registration; + + event.waitUntil(async () => { + const registration = event.registration; + const records = await registration.matchAll(); + const responsePromises = records.map( + async (record) => await record.responseReady, + ); + + const responses = Promise.all(responsePromises); + // レスポンスで何かを行う + }); +}); +``` + +ハンドラーが終了するとレスポンスデータは利用できなくなるので、アプリがまだデータを必要としているので、ハンドラーはそのデータを(例えば {{domxref("Cache")}} に)格納しておく必要があります。 + +#### ブラウザーの UI の更新 + +`backgroundfetchsuccess` と `backgroundfetchfail` に渡されるイベントオブジェクトには {{domxref("BackgroundFetchUpdateUIEvent/updateUI", "updateUI()")}} メソッドがあり、ブラウザーが表示する UI を更新してユーザーに読み取り処理を通知するために使用することができます。`updateUI()` を使うと、ハンドラーは U I要素のタイトルとアイコンを更新することができます。 + +```js +// service-worker.js + +self.addEventListener("backgroundfetchsuccess", (event) => { + // レスポンスデータの取得と格納 + // ... + + event.updateUI({ title: "ダウンロードが完了しました。" }); +}); + +self.addEventListener("backgroundfetchfail", (event) => { + event.updateUI({ title: "ダウンロードが完了できませんでした。" }); +}); +``` + +#### ユーザー操作への応答 + +`backgroundfetchclick` イベントは、フェッチ中にユーザーがブラウザーが表示させる UI 要素をクリックしたときに発行されます。 + +ここで期待されるレスポンスは、フェッチ処理に関する詳細情報をユーザーに与えるウィンドウを開くためのもので、サービスワーカーから {{domxref("Clients/openWindow", "clients.openWindow()")}} を使用して実行することができます。例えば、次のようになります: + +```js +// service-worker.js + +self.addEventListener("backgroundfetchclick", (event) => { + const registration = event.registration; + + if (registration.result === "success") { + clients.openWindow("/play-movie"); + } else { + clients.openWindow("/movie-download-progress"); + } +}); +``` + +## 定期バックグラウンド同期 + +[定期バックグラウンド同期 API](/ja/docs/Web/API/Web_Periodic_Background_Synchronization_API) により、PWA はメインアプリが閉じられている間、バックグラウンドで定期的にデータを更新することができます。 + +これにより、PWA が提供するオフライン体験を大幅に改善することができます。ニュースアプリのような、適度に新しいコンテンツに依存するアプリを考えてみましょう。ユーザーがアプリを開くための端末がオフラインの場合、サービスワーカーベースのキャッシュを使用しても、ストーリーの鮮度はアプリが最後に開かれた時点と同じにしかなりません。定期バックグラウンド同期があれば、アプリは端末が接続可能なときにバックグラウンドでストーリーを更新することができ、相対的に新鮮なコンテンツをユーザーに表示させることができます。 + +これは、特にモバイル端末では、接続性が悪いというよりも「断続的」であるという事実を利用しています。端末が接続性を持っている時間を利用することで、アプリは接続性のギャップを滑らかにすることができます。 + +### 定期同期イベントの登録 + +定期的な同期イベントを登録するコードは、[同期イベントの登録](#同期イベントの登録)と同じパターンに従います。{{domxref("ServiceWorkerRegistration")}} には {{domxref("ServiceWorkerRegistration.periodicSync", "periodicSync")}} プロパティがあり、定期同期の名前を引数に取る {{domxref("PeriodicSyncManager/register", "register()")}} メソッドがあります。 + +ただし、`periodicSync.register()` は追加の引数として `minInterval` プロパティを持つオブジェクトを取ります。これは同期を試みる最小間隔をミリ秒で表します。 + +```js +// main.js + +async function registerPeriodicSync() { + const swRegistration = await navigator.serviceWorker.ready; + swRegistration.periodicSync.register("update-news", { + // try to update every 24 hours + minInterval: 24 * 60 * 60 * 1000, + }); +} +``` + +### 定期同期イベントの処理 + +PWA は `register()` 呼び出しで具体的な間隔を要求しますが、定期的な同期イベントを生成する頻度はブラウザー次第です。ユーザーが頻繁に開いて操作するためのアプリは、ユーザーがほとんど対話しないアプリよりも定期的な同期イベントを受信する可能性が高く、受信頻度も高くなります。 + +ブラウザーが定期同期イベントを生成することを決定した場合、パターンは次のようになります: 必要に応じてサービスワーカーを開始し、サービスワーカーのグローバルスコープで {{domxref("ServiceWorkerGlobalScope.periodicsync_event", "periodicSync")}} イベントを発行します。 + +サービスワーカーのイベントハンドラーはイベントの名前を調べ、イベントの {{domxref("ExtendableEvent/waitUntil", "waitUntil()")}} メソッド内の適切な関数を呼び出します。 + +```js +// service-worker.js + +self.addEventListener("periodicsync", (event) => { + if (event.tag === "update-news") { + event.waitUntil(updateNews()); + } +}); +``` + +`updateNews()`の中で、サービスワーカーは最新の記事を読み取ってキャッシュすることができます。`updateNews()` 関数は相対的にすばやく完了する必要があります。サービスワーカーのコンテンツ更新に時間がかかりすぎると、ブラウザーはそれを停止します。 + +### 定期同期の登録解除 + +PWA が定期的なバックグラウンド更新を必要としなくなった場合(例えば、ユーザーがアプリの設定で定期同期をオフにした場合など)、PWA は {{domxref("serviceWorkerRegistration.periodicSync", "periodicSync")}} の {{domxref("PeriodicSyncManager/unregister", "unregister()")}} メソッドを呼び出して、定期同期イベントの生成を停止するようブラウザーに依頼する必要があります。 + +```js +// main.js + +async function registerPeriodicSync() { + const swRegistration = await navigator.serviceWorker.ready; + swRegistration.periodicSync.unregister("update-news"); +} +``` + +## プッシュ通知 + +[プッシュ通知 API](/ja/docs/Web/API/Push_API) を使うと、PWA はアプリが実行されているかどうかに関わらず、サーバーからプッシュされたメッセージを受け取ることができます。端末がメッセージを受信すると、アプリのサービスワーカークリプトが開始され、メッセージを処理し、[通知](/ja/docs/Web/API/Notifications_API)をユーザーに表示させます。この仕様では、通知を示さない「サイレントプッシュ」も可能ですが、プライバシーの問題(例えば、プッシュがユーザーの位置情報を使用することができます)から、どのブラウザーも対応していません。 + +ユーザーに通知を表示すると、ユーザーが行っているあらゆるものから気をそらすことになり、とても迷惑になる可能性があるので、プッシュメッセージは注意して使用してください。一般的には、ユーザーに何かを知らせる必要があり、次にアプリを開くための時点まで待つことができないような状況に適しています。 + +プッシュ通知の一般的な使用用途はチャットアプリです。ユーザーが連絡先からメッセージを受信すると、それはプッシュメッセージとして配信され、アプリは通知を示します。 + +プッシュメッセージは、アプリサーバーから端末に直接送信されません。アプリサーバーはプッシュサービスにメッセージを送信し、そこから端末がメッセージを取得してアプリに配信します。 + +これは、サーバーからプッシュサービスへのメッセージは{{Glossary("Encryption", "暗号化")}}し(プッシュサービスが読み取れないようにするため)、{{Glossary("Signature/Security", "署名")}}する(プッシュサービスが、自分のサーバーからのメッセージであり、自分のサーバーになりすました誰かからのメッセージではないことを本当に知るため)ことが必要であることも意味しています。 + +プッシュサービスは、ブラウザーベンダーまたはサードパーティによって運営され、アプリサーバーは [HTTP Push](https://datatracker.ietf.org/doc/html/rfc8030) プロトコルを使用してプッシュサービスと通信します。ウェブサーバーは [web-push](https://github.com/web-push-libs/web-push) のようなサードパーティライブラリーを使用して、プロトコルの詳細を世話することができます。 + +### プッシュメッセージの購読 + +プッシュメッセージを購読するパターンは次のようになります。 + +![プッシュメッセージ購読の手順を示す図](push-messaging-1.svg) + +1. 前提条件として、アプリサーバーで{{Glossary("Public-key_cryptography", "公開/秘密鍵ペア")}}を用意しておく必要があります。メッセージへの署名は [VAPID](https://datatracker.ietf.org/doc/html/draft-thomson-webpush-vapid-02) 仕様に従う必要があります。 + +2. 端末上では、アプリは {{domxref("PushManager.subscribe()")}} メソッドを使用してサーバーからのメッセージを購読します。`subscribe()` メソッドは次のようになります。 + + - 引数としてアプリサーバーの公開鍵を用います。これは、プッシュサービスがアプリサーバーからのメッセージの署名を検証するために使用するものです。 + + - {{domxref("PushSubscription")}} オブジェクトで解決する `Promise` を返します。このオブジェクトには以下のものが含まれています。 + + - プッシュサービスの[エンドポイント](/ja/docs/Web/API/PushSubscription/endpoint): アプリサーバーがプッシュメッセージの送信先を知るためのものです。 + - サーバーがプッシュサービスへのメッセージを暗号化するために使用する[公開鍵](/ja/docs/Web/API/PushSubscription/getKey)。 + +3. アプリはエンドポイントと公開鍵をサーバーに(例えば {{domxref("WorkerGlobalScope/fetch", "fetch()")}}を使用して)送信します。 + +この後、アプリサーバーはプッシュメッセージの送信を始めることができます。 + +### プッシュメッセージの送信、配信、処理 + +サーバー上でアプリに処理させたいイベントが発生すると、サーバーはメッセージを送ることができ、その一連の流れは次のようになります。 + +![プッシュメッセージの送信と配信の手順を示す図](push-messaging-2.svg) + +1. アプリサーバーは、署名用の秘密鍵を使用してメッセージに署名し、プッシュサービスの暗号化用の公開鍵を使用してメッセージを暗号化します。ウェブサーバーは [web-push](https://github.com/web-push-libs/web-push) のようなライブラリーを使用することができます。 +2. ウェブサーバーは、[HTTP Push](https://datatracker.ietf.org/doc/html/rfc8030) プロトコルを用いて、プッシュサービスのエンドポイントにメッセージを送信し、こちらでも web-push のようなライブラリーを使用することができます。 +3. プッシュサービスはメッセージの署名を調べ、署名が有効であれば、プッシュサービスは配信のためにメッセージをキューに入れます。 +4. 端末にネットワーク接続がある場合、プッシュサービスは暗号化されたメッセージをブラウザーに配信します。 +5. ブラウザーは暗号化されたメッセージを受信すると、メッセージを復号します。 +6. ブラウザーは必要に応じてサービスワーカーを開始し、サービスワーカーのグローバルスコープで {{domxref("ServiceWorkerGlobalScope.push_event", "push")}} というイベントを呼び出されます。イベントハンドラーには {{domxref("PushEvent")}} オブジェクトが渡され、メッセージデータを格納します。 +7. イベントハンドラーでは、サービスワーカーはメッセージの処理を行います。いつものように、イベントハンドラーは `event.waitUntil()` を呼び出して、サービスワーカーを実行し続けるようにブラウザーに依頼します。 +8. そのイベントハンドラーで、サービスワーカーは {{domxref("ServiceWorkerRegistration/showNotification", "registration.showNotification()")}} を使用して通知を作成します。 +9. ユーザーが通知をクリックしたり閉じたりすると、サービスワーカーのグローバルスコープでそれぞれ {{domxref("ServiceWorkerGlobalScope.notificationclick_event", "notificationclick")}} と {{domxref("ServiceWorkerGlobalScope.notificationclose_event", "notificationclose")}} が発行されます。これらにより、アプリは通知に対するユーザーのレスポンスを処理することができます。 + +## 権限と制限 + +ブラウザーは、ウェブ開発者に強力な API を提供する一方で、悪意のある、悪用されやすい、またはお粗末に書かれたウェブサイトからユーザーを保護するためのバランスを見つけなければなりません。ブラウザーが提供する主な保護の1つは、ユーザーがウェブサイトのページを閉じれば、端末上でそのウェブサイトがアクティブでなくなることです。この記事で記述している API はその保証を破る傾向があるため、ブラウザーはユーザーがこのことを認識し、API がユーザーの関心に沿った方法で使用されることを保証するために特別な段階を踏まなければなりません。 + +この節ではこれらの段階の概要を説明します。これらの API のいくつかは明示的な[ユーザーの許可](/ja/docs/Web/API/Permissions_API)が要求され、他にもユーザーを保護するための様々な制限や設計上の選択があります。 + +- バックグラウンド同期 API はユーザーからの明示的な許可を必要としませんが、バックグラウンド同期リクエストの発行は主要アプリが開いている間のみ行うことができ、ブラウザーはバックグラウンド同期処理の再試行回数と時間を制限します。 + +- バックグラウンドフェッチ API はユーザーからの `"background-fetch"` の許可を要求され、ブラウザーはフェッチ処理の進行状況を表示し、ユーザーはその処理を取り消すことが可能です。 + +- 定期バックグラウンド同期 API はユーザーからの `"periodic-background-sync"` の許可を要求されます。ブラウザーはユーザーが定期バックグラウンド同期を完全に無効にできるようにする必要があります。また、ブラウザーは同期イベントの頻度を、ユーザーがアプリと対話することを選ぶ程度に関連付けることができます。そのため、ユーザーがほとんど使用しないアプリは、イベントをほとんど受け取らない(あるいはまったく受け取らない)かもしれません。 + +- 通知 API はユーザーからの `"push"` の許可をを要求され、すべてのブラウザーはプッシュイベントがユーザー可視であること、つまりユーザー可視通知を生成することを要求します。 + +## 関連情報 + +### リファレンス + +- [サービスワーカー API](/ja/docs/Web/API/Service_Worker_API) +- [バックグラウンド同期 API](/ja/docs/Web/API/Background_Synchronization_API) +- [バックグラウンドフェッチ API](/ja/docs/Web/API/Background_Fetch_API) +- [定期バックグラウンド同期 API](/ja/docs/Web/API/Web_Periodic_Background_Synchronization_API) +- [プッシュ API](/ja/docs/Web/API/Push_API) +- [通知 API](/ja/docs/Web/API/Notifications_API) + +### ガイド + +- [Introducing Background Sync](https://developer.chrome.com/blog/background-sync/) (developer.chrome.com, 2017) +- [Introducing Background Fetch](https://developer.chrome.com/blog/background-fetch/) (developer.chrome.com, 2022) +- [The Periodic Background Sync API](https://developer.chrome.com/docs/capabilities/periodic-background-sync) (developer.chrome.com, 2020) +- [Notifications](https://web.dev/explore/notifications) (web.dev) +- [PWA with offline streaming](https://web.dev/articles/pwa-with-offline-streaming) (web.dev, 2021) diff --git a/files/ja/web/progressive_web_apps/guides/offline_and_background_operation/push-messaging-1.svg b/files/ja/web/progressive_web_apps/guides/offline_and_background_operation/push-messaging-1.svg new file mode 100644 index 00000000000000..bf3eb9197c8b4f --- /dev/null +++ b/files/ja/web/progressive_web_apps/guides/offline_and_background_operation/push-messaging-1.svg @@ -0,0 +1 @@ +
アプリサーバー
アプリサーバー
ブラウザー
ブラウザー
メインアプリ
メインアプリ
1. サーバーへの
署名鍵の提供
1. サーバーへの
2. PushManager.subscribe()
2. PushManager.subscribe()
3. アプリサーバーへの送信
- プッシュサービスのエンドポイント
- プッシュサービスの公開鍵
3. アプリサーバーへの送信...
端末
端末
\ No newline at end of file diff --git a/files/ja/web/progressive_web_apps/guides/offline_and_background_operation/push-messaging-2.svg b/files/ja/web/progressive_web_apps/guides/offline_and_background_operation/push-messaging-2.svg new file mode 100644 index 00000000000000..967a168653fd77 --- /dev/null +++ b/files/ja/web/progressive_web_apps/guides/offline_and_background_operation/push-messaging-2.svg @@ -0,0 +1 @@ +
アプリサーバー
アプリサーバー
プッシュサービス
プッシュサービス
ブラウザー
ブラウザー
サービスワーカー
サービスワーカー
2. プッシュメッセージを送信
2. プッシュメッセージを送信
4. 暗号化された
プッシュメッセージ
を送信
4. 暗号化されたプッシュメッセージを送信
3. プッシュ
メッセージの
署名を検証
3. プッシュメッセージの署名を検証
端末
端末
5. プッシュ
メッセージ
を復号
5. プッシュメッセージ

を復号
6. メッセージを含む
プッシュイベントを発行
6. メッセージを含むプッシュイベントを発行
7. メッセージ
を処理
7. メッセージを処理
8. 通知を表示
8. 通知を表示
1. プッシュメッセージ
を暗号化して署名
1. プッシュメッセージを暗号化して署名
9. 通知の
応答を
処理
9. 通知の応答を処理
\ No newline at end of file From 5de36446596c6584ba1b40b6982ddbc086a9588a Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 12 Aug 2024 17:21:00 +0900 Subject: [PATCH 04/28] =?UTF-8?q?2024/07/26=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=96=B0=E8=A6=8F=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../guides/caching/index.md | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 files/ja/web/progressive_web_apps/guides/caching/index.md diff --git a/files/ja/web/progressive_web_apps/guides/caching/index.md b/files/ja/web/progressive_web_apps/guides/caching/index.md new file mode 100644 index 00000000000000..c55b4eee37dabe --- /dev/null +++ b/files/ja/web/progressive_web_apps/guides/caching/index.md @@ -0,0 +1,214 @@ +--- +title: キャッシュ +slug: Web/Progressive_web_apps/Guides/Caching +l10n: + sourceCommit: 5c000c8621145c6915f3d545b505c216317bc64a +--- + +{{PWASidebar}} + +ユーザーがウェブサイトを開いて操作するとき、ウェブサイトが必要とするすべてのリソース(HTML、JavaScript、CSS、画像、フォント、およびアプリが明示的にリクエストされたデータを含む)は、HTTP(S) リクエストによって取得されます。PWA の最も基本的な機能の 1 つは、アプリのリソースの一部を端末に明示的にキャッシュする機能です。これは、ネットワークにリクエストを送信する必要なく、リソースを取得できるということです。 + +リソースをローカルにキャッシュすることには、主に 2 つの好ましいことがあります: **オフライン操作**と**応答性**です。 + +- **オフライン操作**: キャッシュにより、端末がネットワークに接続していない間でも、PWA が多かれ少なかれ機能することができます。 +- **応答性**: 端末がオンラインであっても、ユーザーインターフェイスがネットワークではなくキャッシュから取得される場合、PWA は通常はるかに応答性が良くなります。 + +もちろん、主な欠点は**鮮度** です。キャッシュは最新である必要があるリソースにはあまり適していません。また、[POST](/ja/docs/Web/HTTP/Methods/POST) リクエストのようなリクエストの型によっては、キャッシュは決して適切ではありません。 + +これは、リソースをキャッシュすべきかどうか、そしていつキャッシュすべきかは、問題のリソースに強く依存し、PWA は通常、さまざまなリソースに対して異なる戦略を採用するということを意味しています。このガイドでは、PWA 向けの一般的なキャッシュ戦略を見ていき、どの戦略がどのリソースに対して意味があるのかを見ていきます。 + +## キャッシュ技術の概要 + +PWA がキャッシュ戦略を構築できる主な技術は、[フェッチ API](/ja/docs/Web/API/Fetch_API)、[サービスワーカー API](/ja/docs/Web/API/Service_Worker_API)、[キャッシュ API](/ja/docs/Web/API/Cache) です。 + +### フェッチ API + +フェッチ API は、ネットワークリソースを取得するためのグローバル関数 {{domxref("WorkerGlobalScope/fetch", "fetch()")}} と、ネットワークリクエストとレスポンスを表すインターフェイス {{domxref("Request")}} と {{domxref("Response")}} を定義します。`fetch()` 関数は `Request` または URL を引数として取り、`Response` を解決する {{jsxref("Promise")}} を返します。 + +`fetch()` 関数はメインスレッドだけでなくサービスワーカーも利用できます。 + +### サービスワーカー API + +サービスワーカーは PWA の一部で、アプリのメインスレッドとは別の、自分自身で実行するスクリプトです。 + +サービスワーカーがアクティブになると、アプリがサービスワーカーが制御するネットワークリソースをリクエストするたびに、ブラウザーはサービスワーカーのグローバルスコープで {{domxref("ServiceWorkerGlobalScope.fetch_event", "fetch")}} というイベントを呼び出します。このイベントは、メインスレッドからの `fetch()` の明示的な呼び出しだけでなく、ブラウザーがページナビゲーションに従うことで行う、ページやサブリソース(JavaScript、CSS、画像など)を読み込むための暗黙的なネットワークリクエストに対しても発生します。 + +`fetch` イベントを待ち受けすることで、サービスワーカーはリクエストを介入し、カスタマイズしたレスポンス (`Response`) を返すことができます。具体的には、常にネットワークにアクセスする代わりにローカルにキャッシュされたレスポンスを返したり、端末がオフラインの場合にローカルにキャッシュされたレスポンスを返したりすることができます。 + +### キャッシュ API + +{{domxref("Cache")}} インターフェイスは `Request`/`Response` ペアの永続的なストレージを提供します。これは `Request`/`Response` のペアを追加したり削除したり、指定された `Request` に一致するキャッシュされた `Response` を参照するメソッドを提供します。キャッシュはメインスレッドとサービスワーカーの両方で利用できます。あるスレッドでレスポンスを追加し、別のスレッドでそれを取得することが可能です。 + +ほとんどの場合、サービスワーカーは `install` または `fetch` イベントハンドラーでキャッシュにリソースを追加します。 + +## いつリソースをキャッシュするか + +PWA はいつでもリソースをキャッシュできますが、実際には、ほとんどの PWA がリソースをキャッシュすることを選ぶ時点がいくつかあります。 + +- **サービスワーカーの `install` イベントハンドラー (事前キャッシュ)**: サービスワーカーがインストールされると、ブラウザーはサービスワーカーのグローバルスコープで {{domxref("ServiceWorkerGlobalScope.install_event", "install")}} というイベントを呼び出します。この点で、サービスワーカーはリソースを事前キャッシュすることができ、ネットワークからフェッチしてキャッシュに格納することができます。 + + > [!NOTE] + > サービスワーカーのインストール時点は、PWA のインストール時点とは異なります。サービスワーカーの `install` イベントは、サービスワーカーがダウンロードされ、実行されるとすぐに発生します。 + > + > ユーザーがサイトを PWA としてインストールしなくても、サービスワーカーはインストールされ、有効化されます。 + +- **サービスワーカーの `fetch` イベントハンドラーで**: サービスワーカーの `fetch` イベントが発行されると、サービスワーカーはリクエストをネットワークに転送し、キャッシュにまだレスポンスが格納されていない場合、またはキャッシュされたレスポンスをより新しいものに更新するために、結果のレスポンスをキャッシュします。 + +- **ユーザーのリクエストへの応答**: PWA は、端末がオフラインの場合に、後で使用するリソースをダウンロードするようユーザーを明示的に促すことがあります。例えば、音楽プレーヤーは、後で再生するためにトラックをダウンロードするようユーザーを促すかも しれません。この場合、メインアプリのスレッドがリソースを取得し、レスポンスをキャッシュに追加する可能性があります。特にリクエストされたリソースが大きい場合、PWA は[バックグラウンド API](/ja/docs/Web/API/Background_Fetch_API) を使用し、この場合レスポンスはサービスワーカーによって処理され、キャッシュに追加されます。 + +- **定期的に**: [定期バックグラウンド同期 API](/ja/docs/Web/API/Web_Periodic_Background_Synchronization_API) を使用することができます。サービスワーカーは定期的にリソースを取得してレスポンスをキャッシュし、端末がオフラインの間でも PWA が適度に新鮮なレスポンスを提供できるようにします。 + +## キャッシュ戦略 + +キャッシュ戦略とは、いつリソースをキャッシュするか、いつキャッシュされたリソースを提供するか、いつネットワークからリソースを取得するかのアルゴリズムです。この節では、一般的な戦略をいくつかまとめます。 + +これは網羅的なリストではなく、PWA が取り得る手法の種類を示すためのものです。 + +キャッシュ戦略はオフライン操作、レスポンス、鮮度のバランスを取ります。例えば、アプリの基本的な UI は相対的に静的である可能性が高い一方で、商品リストを表示する際には新鮮なデータを持つことができることが不可欠かもしれません。このことは、PWA がリソースごとに異なる戦略を採用するのが一般的であり、単一の PWA がここで記述する戦略をすべて使用する可能性があるということを意味しています。 + +### キャッシュ優先 + +この戦略では、いくつかのリソースを事前にキャッシュし、それらのリソースに対してのみ「キャッシュ優先」戦略を実装します。つまり、 + +- 事前キャッシュされたリソースについては、 + - キャッシュからリソースを探して、得られたらリソースを返します。 + - そうでない場合は、ネットワークに移動します。ネットワークリクエストが成功した場合は、次回に備えてリソースをキャッシュします。 +- 他のリソースについては、常にネットワークにアクセスします。 + +事前キャッシュは、PWA が確実に必要とし、このバージョンのアプリでは変更されず、可能な限りすばやく取得する必要があるリソースに対して適切な戦略です。これには例えばアプリの基本ユーザーインターフェイスが含まれます。これが事前にキャッシュされていれば、アプリの UI は起動時にネットワークリクエストを必要とせずにレンダリングできます。 + +最初に、サービスワーカーは `install` イベントハンドラーで静的リソースを事前キャッシュします。 + +```js +const cacheName = "MyCache_1"; +const precachedResources = ["/", "/app.js", "/style.css"]; + +async function precache() { + const cache = await caches.open(cacheName); + return cache.addAll(precachedResources); +} + +self.addEventListener("install", (event) => { + event.waitUntil(precache()); +}); +``` + +`install` イベントハンドラーでは、キャッシュ操作の結果をイベントの {{domxref("ExtendableEvent.waitUntil", "waitUntil()")}} メソッドに渡します。これは、キャッシュが何らかの理由で失敗した場合、サービスワーカーのインストールが失敗するということです。逆に、インストールが成功した場合、サービスワーカーはリソースがキャッシュに追加されたことを確認することができます。 + +`fetch` イベントハンドラーは次のようになります。 + +```js +async function cacheFirst(request) { + const cachedResponse = await caches.match(request); + if (cachedResponse) { + return cachedResponse; + } + try { + const networkResponse = await fetch(request); + if (networkResponse.ok) { + const cache = await caches.open("MyCache_1"); + cache.put(request, networkResponse.clone()); + } + return networkResponse; + } catch (error) { + return Response.error(); + } +} + +self.addEventListener("fetch", (event) => { + if (precachedResources.includes(url.pathname)) { + event.respondWith(cacheFirst(event.request)); + } +}); +``` + +イベントの {{domxref("FetchEvent.respondWith()", "respondWith()")}} メソッドを呼び出してリソースを返します。指定されたリクエストに対して `respondWith()` を呼び出さなかった場合、そのリクエストはサービスワーカーが介入しなかったかのようにネットワークに送られます。つまり、プリキャッシュされていないリクエストは、そのままネットワークに送られます。 + +`networkResponse` をキャッシュに追加するときは、レスポンスを複製してコピーをキャッシュに追加し、オリジナルを返さなければなりません。これは `Response` オブジェクトはストリーム可能なので、一度しか読み取れないからです。 + +なぜキャッシュされたリソースをネットワークにフォールバックするのか不思議に思うかもしれません。もしキャッシュされているのであれば、確実にキャッシュにあるはずでは ないでしょうか?その理由は、ブラウザーやユーザーによってキャッシュがクリアされる可能性があるからです。その可能性は低いですが、ネットワークにフォールバックできない限り、PWA は使えなくなります。[キャッシュされたデータの削除](#キャッシュされたデータの削除)を参照してください。 + +### キャッシュ更新付きのキャッシュ優先 + +「キャッシュ優先」の欠点は、一度レスポンスがキャッシュに入ると、 サービスワーカーの新しいバージョンがインストールされるまで更新されないことです。 + +「キャッシュ更新付きのキャッシュ優先」戦略は、キャッシュがヒットした後でも常にリクエストをネットワークに送り、キャッシュを更新するためにレスポンスを使用することを除けば「キャッシュ優先」戦略と似ています。これは、「キャッシュ優先」の応答性を得ながら、(リクエストが適度に多い場合に)かなり新鮮なレスポンスを取得できるということです。 + +これは、レスポンスが重要であり、新鮮さが多少重要であるが必須ではない場合に良い選択です。 + +このバージョンでは、JSON を除くすべてのリソースに対して「キャッシュ更新付きのキャッシュ優先」を実装しています。 + +```js +function isCacheable(request) { + const url = new URL(request.url); + return !url.pathname.endsWith(".json"); +} + +async function cacheFirstWithRefresh(request) { + const fetchResponsePromise = fetch(request).then(async (networkResponse) => { + if (networkResponse.ok) { + const cache = await caches.open("MyCache_1"); + cache.put(request, networkResponse.clone()); + } + return networkResponse; + }); + + return (await caches.match(request)) || (await fetchResponsePromise); +} + +self.addEventListener("fetch", (event) => { + if (isCacheable(event.request)) { + event.respondWith(cacheFirstWithRefresh(event.request)); + } +}); +``` + +非同期で(`then()` ハンドラーの中で)キャッシュを更新しているので、アプリはキャッシュされたレスポンスを使用することができるようになる前にネットワークレスポンスを受信するのを待つ必要はないことに注意してください。 + +### ネットワーク優先 + +最後の「ネットワーク優先」は、キャッシュ優先の逆で、ネットワークからリソースを取得しようとします。ネットワークリクエストが成功したら、レスポンスを返してキャッシュを更新します。失敗した場合は、キャッシュを試します。 + +これは、可能な限り新鮮なレスポンスを取得することが重要だが、キャッシュされたリソースはないよりはましというリクエストに有益です。メッセージングアプリの最近のメッセージのリストがこのカテゴリーに入るかもしれません。 + +この例では、アプリの "inbox" パスの下にあるすべてのリソースを読み取るリクエストに「ネットワーク優先」を使用しています。 + +```js +async function networkFirst(request) { + try { + const networkResponse = await fetch(request); + if (networkResponse.ok) { + const cache = await caches.open("MyCache_1"); + cache.put(request, networkResponse.clone()); + } + return networkResponse; + } catch (error) { + const cachedResponse = await caches.match(request); + return cachedResponse || Response.error(); + } +} + +self.addEventListener("fetch", (event) => { + const url = new URL(event.request.url); + if (url.pathname.match(/^\/inbox/)) { + event.respondWith(networkFirst(event.request)); + } +}); +``` + +古くなる可能性のあるレスポンスより、レスポンスがない方が良いリクエストや、「ネットワークのみ」戦略が適切なリクエストもあります。例えば、アプリが利用できる商品のリストを表示させている場合、そのリストが古いとユーザーはイライラするでしょう。 + +## キャッシュされたデータの削除 + +キャッシュが持つストレージ空間の大きさには制限があり、制限を超えるとブラウザーはアプリのキャッシュデータを削除することができます。具体的な制限値と動作はブラウザーによって異なります。詳細は[ストレージ制限と削除基準](/ja/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria)を参照してください。実際には、キャッシュされたデータが消去されることは非常に稀なことです。ユーザーはいつでもアプリのキャッシュをクリアできます。 + +PWA はサービスワーカーの {{domxref("ServiceWorkerGlobalScope.activate_event", "activate")}} イベントで古いバージョンのキャッシュを一掃する必要があります。このイベントが発行されると、サービスワーカーは前回実行したバージョンのサービスワーカーがないことを確認できるので、古いキャッシュデータはできなくなります。 + +## 関連情報 + +- [サービスワーカー API](/ja/docs/Web/API/Service_Worker_API) +- [フェッチ API](/ja/docs/Web/API/Fetch_API) +- [ストレージ制限と削除基準](/ja/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria) +- [Strategies for service worker caching](https://developer.chrome.com/docs/workbox/caching-strategies-overview) (developer.chrome.com, 2021) +- [The Offline Cookbook](https://web.dev/articles/offline-cookbook) (web.dev, 2020) From 9604a02a7a49990172cc1522f8ed57f5f5ea3cc9 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 12 Aug 2024 22:46:21 +0900 Subject: [PATCH 05/28] =?UTF-8?q?2024/07/30=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=96=B0=E8=A6=8F=E7=BF=BB=E8=A8=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../guides/best_practices/index.md | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 files/ja/web/progressive_web_apps/guides/best_practices/index.md diff --git a/files/ja/web/progressive_web_apps/guides/best_practices/index.md b/files/ja/web/progressive_web_apps/guides/best_practices/index.md new file mode 100644 index 00000000000000..d47e6d995ddd79 --- /dev/null +++ b/files/ja/web/progressive_web_apps/guides/best_practices/index.md @@ -0,0 +1,105 @@ +--- +title: PWA のベストプラクティス +slug: Web/Progressive_web_apps/Guides/Best_practices +l10n: + sourceCommit: e03b13c7e157ec7b7bb02a6c7c4854b862195905 +--- + +{{PWASidebar}} + +[プログレッシブウェブアプリ](/ja/docs/Web/Progressive_web_apps) (PWA) は端末にインストールすることができ、ウェブブラウザーで従来のウェブサイトとして使用することができます。これは、PWA が異なる環境や異なるユーザーの期待に適応できる必要があるということです。 + +この記事では、PWA を可能な限り優れたものにするために役立つベストプラクティスのリストを提供します。 + +## すべてのブラウザーに適応する + +PWAはウェブ技術に基づいています。これは、端末にインストールできることに加えて、PWAはウェブブラウザーでも実行できるということを意味しています。互換性を保証するためには、さまざまなブラウザーや OS で [アプリのテスト](/ja/docs/Learn/Tools_and_testing/Cross_browser_testing) を行うことが不可欠です。 + +ユーザーが使用する可能性のある多様な範囲のブラウザーを考慮し、幅広い潜在的なユーザーに合わせなければなりません。[機能検出](/ja/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_detection)を使用することで、幅広いユーザーに有益な体験を提供することができます。 + +機能検出は、{{Glossary("Progressive Enhancement", "プログレッシブエンハンスメント")}}(できるだけ多くのユーザーに優れた使い勝手を提供することを可能にする設計思想)にも役立ちます。 + +プログレッシブエンハンスメントでは、最もシンプルな技術を使用してアプリのコア機能を最初に普遍的に動作させることに集中し、次に対応している端末の使い勝手を向上させます。 + +例えば、フォーム送信を HTML の {{htmlelement("form")}} 要素で処理すれば、フォームが JavaScript をサポートしていないブラウザーを含むすべてのブラウザーで動作することになります。その後、クライアント側の検証や JavaScript ベースの送信処理を追加することでフォームを徐々に強化し、対応している端末での使い勝手を向上させることができます。 + +## すべての端末に適応する + +さまざまなブラウザーでアプリをテストすることが重要であるのと同様に、すべての端末でテストすることで、アプリが多くのユーザーにアクセスされることを保証します。 + +[レスポンシブデザイン](/ja/docs/Learn/CSS/CSS_layout/Responsive_Design)は、PWA にとって、確実にどの画面サイズでもコンテンツにアクセスすることを保証するために重要です。ユーザーは端末の画面サイズに関係なく、すべての機能やコンテンツにアクセスできる必要があります。ビューポートサイズごとにコンテンツを並べ替えることで、重要なデータやアクションに優先順位をつけることができます。 + +ユーザーがどのような方法でコンテンツにアクセスしても、アプリケーションを確実に操作できるように保証しましょう。キーボードやマウスだけでなく、タッチやスタイラスの入力方法にも対応してください。アプリケーションのすべての機能が、どのような入力方法でもアクセスできるようにしてください。 + +最後に、自分自身でボタンやフォーム要素を作り直すのではなく、[意味付けされた HTML 要素](/ja/docs/Glossary/Semantics#semantics_in_html) を使用してください、意味付けされた HTML 要素はすべてのユーザー入力方法にすぐに対応します。 + +## オフラインの利用を提供する + +インストールされたアプリのユーザーは、低速で信頼性の低いネットワークに接続されているときや、端末が完全にオフラインのときでも、常に動作することを期待しています。 + +### 独自のオフラインページ + +少なくとも、PWA は一般的なブラウザーエラーページを表示させる代わりに、オフラインであることをユーザーに知らせる独自のオフラインページを提供する必要があります。独自のオフラインページは、ブラウザーや端末間でより一貫した使い勝手を提供し、ユーザーをアプリに引き付け続けます。 + +[サービスワーカー](/ja/docs/Web/API/Service_Worker_API)を使用して、ネットワークリクエストに介入し、ユーザーがオフラインのときに独自のオフラインページで応答することで、独自のオフラインページを提供することができます。 + +### オフライン操作 + +さらに進んでアプリのような使い勝手を提供するために、PWA はユーザーがオフラインのときにも機能する必要があります。これは、ユーザーがオフラインでもアプリの機能の一部、できればすべてを使用し続けることができる、ということです。 + +ユーザーが長いメールを作成し、ネットワーク接続を失ったことに気づかずに「送信」を押したとします。このアプリはオフラインで動作するので、メールはローカルに保存され、端末がオンラインに戻ったときに自動的に送信されます。 + +詳しくは[オフライン操作とバックグラウンド処理](/ja/docs/Web/Progressive_web_apps/Guides/Offline_and_background_operation)を参照してください。 + +## ディープリンクへの対応 + +ディープリンクは、アプリのドメイン内の特定のページを指すハイパーリンクです。例えば、アプリのトップページは `https://example.com/` で利用できるかもしれませんが、`https://example.com/products/123` で特定の製品ページにリンクすることもできます。 + +特定の URL で任意のリソースを参照する機能は、ウェブの最も強力な機能の1つです。PWA はウェブ技術に基づいて構築されているため、この機能を導くことができますし、導くべきです。 + +アプリの様々な部分を固有の URL から利用できるようにすることで、ユーザーはアプリ内の特定のコンテンツをブックマークしたり、直接移動したり、共有したりすることができます。また、検索エンジンがアプリのコンテンツをインデックスし、ウェブ検索で発見できるようになります。 + +## 高速化する + +ユーザーは、インストールされたアプリに対して、ウェブサイトとは異なる期待を持っています。ユーザーは、特にネットワーク接続が悪い場合、ウェブサイトの読み込みとナビゲーションの時点に時間がかかることを想定しています。しかし、インストール済みアプリには、常に速く、レスポンスよく動作することを期待します。 + +アプリの読み込みとコア機能の実行速度は、ユーザーエンゲージメントと定着率において重要な役割を果たします。アプリの応答に時間がかかるほど、ユーザーはアプリを放棄します。 + +パフォーマンスを測定し、改善するのに役立つツール、API、最善の手法があります。詳しくは、[ウェブパフォーマンス](/ja/docs/Web/Performance)を参照してください。 + +## アクセス可能にする + +アクセシビリティは、個人の能力やアプリにアクセスするために使用する端末に関係なく、誰もがアプリを使用することができるように保証するために非常に重要です。アクセシビリティは、可能な限り多くの人がアプリを使用することができるように保証します。アクセシビリティは法律でも要求されています。さらに、アクセシビリティは多くの場合、永続的または一時的な障碍を持つ人だけでなく、すべての人にとってより使い勝手が良くなります。 + +[アクセシビリティ](/ja/docs/Web/Accessibility)で、あなたのウェブアプリをアクセシブルにする方法を学んでください。 + +## アプリ風の使い勝手を提供する + +### オペレーティングシステムに統合する + +ユーザーは、インストールされた PWA が、インストールされたプラットフォーム専用のアプリのように動作することを期待しています。ユーザーが期待するアプリのような使い勝手を提供するには、何らかの方法でアプリをオペレーティングシステムと統合しましょう。例えば、次のような方法です: + +- [通知 API](/ja/docs/Web/API/Notifications_API) を使用してユーザーの端末に通知を送信します。 +- ウェブアプリマニフェストの [`file_handlers`](/ja/docs/Web/Manifest/file_handlers) メンバーでファイルを処理します。 +- アプリのアイコンに[バッジを表示](/ja/docs/Web/Progressive_web_apps/How_to/Display_badge_on_app_icon)します。 +- [アプリ間のデータ共有](/ja/docs/Web/Progressive_web_apps/How_to/Share_data_between_apps)ができるようにします。 + +[ウェブアプリマニフェストメンバー](/ja/docs/Web/Manifest#メンバー)の多くを使用して、ユーザーの端末上でのアプリの表示方法をカスタマイズしたり、オペレーティングシステム内でより深く統合したりすることができます。 + +### ルック&フィール + +ユーザーがアプリをインストールするのは、ウェブサイトよりも集中した使い勝手を取得し、より効率的にタスクを達成するためです。彼らは、アプリがより合理的で、ごちゃごちゃしておらず、最も重要なタスクに集中していることを期待しています。 + +PWA が以下の点でアプリのような使い勝手を提供するようにしましょう。 + +- [スタンドアロン表示モード](/ja/docs/Web/Progressive_web_apps/How_to/Create_a_standalone_app)を使用して、アプリに自分自身で専用のウィンドウを表示します。 +- [アプリのアイコンを定義](/ja/docs/Web/Progressive_web_apps/How_to/Define_app_icons)します。 +- {{cssxref("@media/prefers-color-scheme", "prefers-color-scheme")}} メディア特性を使用してユーザーの環境設定を検出し、それに応じてアプリのテーマを適応させます。 +- [アプリのテーマと背景色をカスタマイズ](/ja/docs/Web/Progressive_web_apps/How_to/Customize_your_app_colors)して、プラットフォーム専用のアプリのように洗練された使い勝手を提供します。 +- コンテンツを整理し、アプリがユーザーに達成させる最も重要な課題に集中しましょう。これは、従来のウェブサイトによくある大きなヘッダーやフッターを除去し、代わりにメニューの形で置き換えるということを意味しています。 +- `system-ui` の {{cssxref("font-family")}} を使用して、コンテンツをよりプラットフォームネイティブな感じにし、ユーザーがカスタムフォントをダウンロードすることを要求されずに、より速く読み込むようにしましょう。 + +## 関連情報 + +- [What makes a good Progressive Web App](https://web.dev/articles/pwa-checklist) (web.dev, 2022) +- [Best practices for PWAs](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/best-practices) (learn.microsoft.com, 2023) From dda81c66d0f18b2018b9019b02cf2816ad28e587 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 12 Aug 2024 23:19:14 +0900 Subject: [PATCH 06/28] =?UTF-8?q?2024/07/04=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/ja/web/css/contain-intrinsic-block-size/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/ja/web/css/contain-intrinsic-block-size/index.md b/files/ja/web/css/contain-intrinsic-block-size/index.md index ee145f61dffe5d..393f42a91b31bf 100644 --- a/files/ja/web/css/contain-intrinsic-block-size/index.md +++ b/files/ja/web/css/contain-intrinsic-block-size/index.md @@ -2,7 +2,7 @@ title: contain-intrinsic-block-size slug: Web/CSS/contain-intrinsic-block-size l10n: - sourceCommit: 9aff58ba641ce676db1ae5a1955ed6ef81cbc718 + sourceCommit: 1b9f8e62afc890f2f00d6f9043f3ce0ff2ac4dfb --- {{CSSRef}} From 2513130ad95eb6620fb09f49b95cca1a799623cf Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 12 Aug 2024 23:13:23 +0900 Subject: [PATCH 07/28] =?UTF-8?q?sourceCommit=20=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/ja/web/api/animationtimeline/index.md | 2 +- files/ja/web/api/scrolltimeline/axis/index.md | 2 +- files/ja/web/api/scrolltimeline/source/index.md | 2 +- files/ja/web/css/css_scroll-driven_animations/index.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/files/ja/web/api/animationtimeline/index.md b/files/ja/web/api/animationtimeline/index.md index c32fcc5969a41d..71a190b6619b49 100644 --- a/files/ja/web/api/animationtimeline/index.md +++ b/files/ja/web/api/animationtimeline/index.md @@ -2,7 +2,7 @@ title: AnimationTimeline slug: Web/API/AnimationTimeline l10n: - sourceCommit: 4dec42ed700040565e8af0e14ff104054ebc20f5 + sourceCommit: 34bc6ac7c5d03e5891bf94b0d4ebeccb0e7a29e5 --- {{ APIRef("Web Animations") }} diff --git a/files/ja/web/api/scrolltimeline/axis/index.md b/files/ja/web/api/scrolltimeline/axis/index.md index 50ab0f48f96e3e..425d14bd551c1d 100644 --- a/files/ja/web/api/scrolltimeline/axis/index.md +++ b/files/ja/web/api/scrolltimeline/axis/index.md @@ -3,7 +3,7 @@ title: "ScrollTimeline: axis プロパティ" short-title: axis slug: Web/API/ScrollTimeline/axis l10n: - sourceCommit: 7eaac8008ebe00417314379fab2285df23322e73 + sourceCommit: 34bc6ac7c5d03e5891bf94b0d4ebeccb0e7a29e5 --- {{APIRef("Web Animations")}}{{SeeCompatTable}} diff --git a/files/ja/web/api/scrolltimeline/source/index.md b/files/ja/web/api/scrolltimeline/source/index.md index 3cee5752d36fe4..71dbce1297ec82 100644 --- a/files/ja/web/api/scrolltimeline/source/index.md +++ b/files/ja/web/api/scrolltimeline/source/index.md @@ -3,7 +3,7 @@ title: "ScrollTimeline: source プロパティ" short-title: source slug: Web/API/ScrollTimeline/source l10n: - sourceCommit: 7eaac8008ebe00417314379fab2285df23322e73 + sourceCommit: 34bc6ac7c5d03e5891bf94b0d4ebeccb0e7a29e5 --- {{APIRef("Web Animations")}}{{SeeCompatTable}} diff --git a/files/ja/web/css/css_scroll-driven_animations/index.md b/files/ja/web/css/css_scroll-driven_animations/index.md index 97727478e6aba9..1abfb79e87d561 100644 --- a/files/ja/web/css/css_scroll-driven_animations/index.md +++ b/files/ja/web/css/css_scroll-driven_animations/index.md @@ -2,7 +2,7 @@ title: CSS スクロール駆動アニメーション slug: Web/CSS/CSS_scroll-driven_animations l10n: - sourceCommit: 4dec42ed700040565e8af0e14ff104054ebc20f5 + sourceCommit: 4458494807b6f4898d504b6c0af0a45f8031cbf3 --- {{CSSRef}} From 16f9fc30dc96917181fde81c40ebea77e61b1d47 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 12 Aug 2024 23:11:59 +0900 Subject: [PATCH 08/28] =?UTF-8?q?2024/08/08=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/ja/web/api/svgrect/x/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/ja/web/api/svgrect/x/index.md b/files/ja/web/api/svgrect/x/index.md index 7eb7bc6fc10138..4dee418505004d 100644 --- a/files/ja/web/api/svgrect/x/index.md +++ b/files/ja/web/api/svgrect/x/index.md @@ -1,9 +1,9 @@ --- title: "SVGRect: x プロパティ" +short-title: x slug: Web/API/SVGRect/x -original_slug: Web/API/SVGRect/The__X__property l10n: - sourceCommit: e9ffc45746287e0d367fb08c597140f10bffd279 + sourceCommit: cf331ccff0dd88648dc9fe22a14f9aaa595ec4bf --- {{APIRef("SVG")}} From da92b2313da47e74a5fdc8d9b9d957d1f9f24798 Mon Sep 17 00:00:00 2001 From: PADAone <50942816+yo-goto@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:55:48 +0900 Subject: [PATCH 09/28] Fix typo --- .../reference/global_objects/promise/resolve/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/ja/web/javascript/reference/global_objects/promise/resolve/index.md b/files/ja/web/javascript/reference/global_objects/promise/resolve/index.md index ffeb132833f673..c277524f068a25 100644 --- a/files/ja/web/javascript/reference/global_objects/promise/resolve/index.md +++ b/files/ja/web/javascript/reference/global_objects/promise/resolve/index.md @@ -172,7 +172,7 @@ const thenable = { }, }; -Promise.resolve(thenable); // 無z限の再帰を引き起こす +Promise.resolve(thenable); // 無限の再帰を引き起こす ``` ### Promise 以外のコンストラクターに対する resolve() の呼び出し From 05532c686f3e6575c3a650db96fa05ed6f6ac5cc Mon Sep 17 00:00:00 2001 From: xufeiranfree Date: Sat, 17 Aug 2024 12:03:13 +0800 Subject: [PATCH 10/28] fix(zh-cn): add missing word "statement" to improve translation (#23093) Co-authored-by: A1lo --- files/zh-cn/web/javascript/guide/working_with_objects/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/zh-cn/web/javascript/guide/working_with_objects/index.md b/files/zh-cn/web/javascript/guide/working_with_objects/index.md index 0bd65705b2b187..c370b8ff1fa399 100644 --- a/files/zh-cn/web/javascript/guide/working_with_objects/index.md +++ b/files/zh-cn/web/javascript/guide/working_with_objects/index.md @@ -194,7 +194,7 @@ function Car(make, model, year) { var mycar = new Car("Eagle", "Talon TSi", 1993); ``` -该创建了 `mycar` 并且将指定的值赋给它的属性。因而 `mycar.make` 的值是字符串 "Eagle", `mycar.year` 的值是整数 1993,依此类推。 +该语句创建了 `mycar` 并且将指定的值赋给它的属性。因而 `mycar.make` 的值是字符串 `"Eagle"`,`mycar.year` 的值是整数 `1993`,依此类推。 你可以通过调用 `new` 创建任意数量的 `car` 对象。例如: From be55b75dbb1cdbee5c15d9430fc2d47441e67a19 Mon Sep 17 00:00:00 2001 From: 720 <71604450+T34-active@users.noreply.github.com> Date: Sat, 17 Aug 2024 12:08:38 +0800 Subject: [PATCH 11/28] [zh-cn]: update the translation of `arguments.length` data property (#23116) --- .../functions/arguments/length/index.md | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/files/zh-cn/web/javascript/reference/functions/arguments/length/index.md b/files/zh-cn/web/javascript/reference/functions/arguments/length/index.md index e009457f72c170..bf66c801878c96 100644 --- a/files/zh-cn/web/javascript/reference/functions/arguments/length/index.md +++ b/files/zh-cn/web/javascript/reference/functions/arguments/length/index.md @@ -1,32 +1,42 @@ --- title: arguments.length slug: Web/JavaScript/Reference/Functions/arguments/length +l10n: + sourceCommit: c6f0f106b9083984dbf597678def6561729bb459 --- {{jsSidebar("Functions")}} -本次函数调用时传入函数的实参数量。 +**`arguments.length`** 数据属性包含传递给函数的参数数量。 -## Syntax +## 值 -```plain -arguments.length -``` +一个非负整数。 + +{{js_property_attributes(1, 0, 1)}} ## 描述 -arguments.length 表示的是实际上向函数传入了多少个参数,这个数字可以比形参数量大,也可以比形参数量小 (形参数量的值可以通过[Function.length](/zh-CN/docs/JavaScript/Reference/Global_Objects/Function/length)获取到). +`arguments.length` 属性提供了实际传递给函数的参数数量。传递的参数数量可能多于或少于定义的参数数量(参见 {{jsxref("Function.prototype.length")}})。例如下面的函数: + +```js +function func1(a, b, c) { + console.log(arguments.length); +} +``` + +`func1.length` 返回 `3`,因为 `func1` 声明了三个形式参数。然而,`func1(1, 2, 3, 4, 5)` 会记录 `5`,因为 `func1` 被调用时传递了五个参数。同样地,`func1(1)` 会记录 `1`,因为 `func1` 被调用时传递了一个参数。 ## 示例 -### 示例:使用`arguments.length` +### 使用 arguments.length -这个例中,我们定义了一个可以相加任意个数字的函数。 +在此示例中,我们定义了一个可以将两个或多个数字相加的函数。 ```js -function adder(base /*, n2, ... */) { +function adder(base /*, num1, …, numN */) { base = Number(base); - for (var i = 0; i < arguments.length; i++) { + for (let i = 1; i < arguments.length; i++) { base += Number(arguments[i]); } return base; @@ -43,4 +53,7 @@ function adder(base /*, n2, ... */) { ## 参见 -- [Function.length](/zh-CN/docs/JavaScript/Reference/Global_Objects/Function/length) +- [函数](/zh-CN/docs/Web/JavaScript/Guide/Functions)指南 +- [函数](/zh-CN/docs/Web/JavaScript/Reference/Functions) +- {{jsxref("Functions/arguments", "arguments")}} +- [`Function`:`length`](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/length) From b0cd495a1f7cab923f4f01b467b3cdb6bd6e9b3e Mon Sep 17 00:00:00 2001 From: Chunhui Fu Date: Sat, 17 Aug 2024 16:49:08 +0800 Subject: [PATCH 12/28] [zh-cn]: create doc for HTMLPictureElement (#23092) --- .../zh-cn/web/api/htmlpictureelement/index.md | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 files/zh-cn/web/api/htmlpictureelement/index.md diff --git a/files/zh-cn/web/api/htmlpictureelement/index.md b/files/zh-cn/web/api/htmlpictureelement/index.md new file mode 100644 index 00000000000000..dd2746a01e6ab7 --- /dev/null +++ b/files/zh-cn/web/api/htmlpictureelement/index.md @@ -0,0 +1,33 @@ +--- +title: HTMLPictureElement +slug: Web/API/HTMLPictureElement +l10n: + sourceCommit: 387d0d4d8690c0d2c9db1b85eae28ffea0f3ac1f +--- + +{{APIRef("HTML DOM")}} + +**`HTMLPictureElement`** 接口表示 {{HTMLElement("picture")}} HTML 元素,它不实现特定的属性和方法。 + +{{InheritanceDiagram}} + +## 实例属性 + +_无特定属性;从其父接口 {{domxref("HTMLElement")}} 继承属性。_ + +## 实例方法 + +_无特定方法;从其父接口 {{domxref("HTMLElement")}} 继承方法。_ + +## 规范 + +{{Specifications}} + +## 浏览器兼容性 + +{{Compat}} + +## 参见 + +- 实现此接口的 HTML 元素:{{HTMLElement("picture")}} +- {{domxref("HTMLImageElement")}} 和 {{domxref("HTMLSourceElement")}} 接口,通常与 {{HTMLElement("picture")}} 元素结合使用。 From 6a1f6137de7dcb87b37a9b163179115f3174eb12 Mon Sep 17 00:00:00 2001 From: 720 <71604450+T34-active@users.noreply.github.com> Date: Sat, 17 Aug 2024 18:06:34 +0800 Subject: [PATCH 13/28] [zh-cn]: update the translation of Window `back()` method (#23113) Co-authored-by: A1lo --- files/zh-cn/web/api/window/back/index.md | 46 +++++++++++++++++++----- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/files/zh-cn/web/api/window/back/index.md b/files/zh-cn/web/api/window/back/index.md index f36b74b298c957..120c6e151d8a53 100644 --- a/files/zh-cn/web/api/window/back/index.md +++ b/files/zh-cn/web/api/window/back/index.md @@ -1,24 +1,52 @@ --- -title: Window.back() +title: Window:back() 方法 slug: Web/API/Window/back +l10n: + sourceCommit: 44c4ec928281dc2d7c5ea42b7d2c74a2013f16ac --- {{APIRef}}{{ Non-standard_header() }}{{deprecated_header}} -## 总结 +{{domxref("window")}} 接口上过时的非标准方法 `back()` 会将窗口返回到历史记录中的前一个记录。这是 Firefox 特有的方法,已在 Firefox 31 中删除。 -跳转窗口到 history 中的前一个地址,这曾是 Gecko 的方法。请使用标准的 history.back 替代它。 +> [!NOTE] +> 请使用标准的 {{domxref("history.back")}} 方法。 -## Syntax +## 语法 -```plain -window.back() +```js-nolint +back() ``` -## Example +### 参数 + +无。 + +### 返回值 + +无({{jsxref("undefined")}})。 + +## 示例 + +这个简单的示例通过调用 `back()` 来处理“返回”按钮的点击操作。 ```js -function goBack() { - if (canGoBack) window.back(); +function handleMyBackButton() { + if (canGoBack) { + window.back(); + } } ``` + +## 规范 + +不属于任何规范。 + +## 浏览器兼容性 + +这种非标准方法只在 Firefox 中实现过,并在 Firefox 31 中被删除。 + +## 参见 + +- {{domxref("History.back()")}} +- {{domxref("History.forward()")}} From 5bb0053f8096c638abd0787a79339a499f147d79 Mon Sep 17 00:00:00 2001 From: 720 <71604450+T34-active@users.noreply.github.com> Date: Sat, 17 Aug 2024 21:22:23 +0800 Subject: [PATCH 14/28] [zh-cn]: update the translation of Window `blur()` method (#23112) --- files/zh-cn/web/api/window/blur/index.md | 31 ++++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/files/zh-cn/web/api/window/blur/index.md b/files/zh-cn/web/api/window/blur/index.md index a9775e00bc8d95..99520c726401cd 100644 --- a/files/zh-cn/web/api/window/blur/index.md +++ b/files/zh-cn/web/api/window/blur/index.md @@ -1,30 +1,41 @@ --- -title: Window.blur() +title: Window:blur() 方法 slug: Web/API/Window/blur +l10n: + sourceCommit: 44c4ec928281dc2d7c5ea42b7d2c74a2013f16ac --- -{{APIRef}} +{{APIRef}}{{deprecated_header}} -## 总结 +**`Window.blur()`** 方法不起任何作用。 -将焦点移出顶层窗口。 +> [!NOTE] +> 从历史上看,这种方法在编程上相当于用户将焦点从当前窗口中移开。由于某些恶意网站滥用此功能,这种行为已被移除。在 Firefox 中,你可以通过设置 `dom.disable_window_flip` 首选项来启用旧的行为。 ## 语法 -```plain -window.blur() +```js-nolint +blur() ``` +### 参数 + +无。 + +### 返回值 + +无({{jsxref("undefined")}})。 + ## 示例 ```js window.blur(); ``` -## 注意 - -使用 window\.blur() 方法与用户主动将焦点移出顶层窗口本质上是一样的。 - ## 规范 {{Specifications}} + +## 浏览器兼容性 + +{{Compat}} From aa4780aef59c3670dff8c4c9ead6570ea03f8043 Mon Sep 17 00:00:00 2001 From: Hoarfroster Date: Sat, 17 Aug 2024 21:52:47 +0800 Subject: [PATCH 15/28] fr: update Glossary/ATAG (#22954) feat: update translation Co-authored-by: SphinxKnight --- files/fr/glossary/atag/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/fr/glossary/atag/index.md b/files/fr/glossary/atag/index.md index eeb80bde018388..8542ecbf7b3994 100644 --- a/files/fr/glossary/atag/index.md +++ b/files/fr/glossary/atag/index.md @@ -2,15 +2,15 @@ title: ATAG slug: Glossary/ATAG l10n: - sourceCommit: ada5fa5ef15eadd44b549ecf906423b4a2092f34 + sourceCommit: 7a551aaa034fbada3eb99e6fc924a0313b78307f --- {{GlossarySidebar}} -**ATAG** (pour Authoring Tool Accessibility Guidelines en anglais) est une recommandation [W3C](/fr/docs/Glossary/W3C) pour construire des outils de création accessibles et qui produisent des contenus accessibles. +**ATAG** (pour Authoring Tool Accessibility Guidelines en anglais, qu'on peut traduire par « directives d'accessibilité pour les outils de production de contenu ») est une recommandation [W3C](/fr/docs/Glossary/W3C) pour construire des outils de création accessibles et qui produisent des contenus accessibles. ## Voir aussi -- [ATAG dans le cadre de la Web Accessibility Initiative](https://fr.wikipedia.org/wiki/Accessibilité_du_web#Recommandations_pour_les_outils_de_production_de_contenu) sur Wikipédia +- [ATAG dans le cadre de la Web Accessibility Initiative](https://fr.wikipedia.org/wiki/Accessibilité_du_web#Recommandations_pour_les_outils_de_production_de_contenu) sur Wikipédia - [Présentation d'ATAG](https://www.w3.org/WAI/standards-guidelines/atag/) sur le site du W3C (en anglais) - [La recommandation ATAG 2.0](https://www.w3.org/TR/ATAG20/) sur le site du W3C (en anglais) From cd059cbe945a34881fcad1f06fe69d6ca9d1b2f2 Mon Sep 17 00:00:00 2001 From: 720 <71604450+T34-active@users.noreply.github.com> Date: Sun, 18 Aug 2024 14:58:45 +0800 Subject: [PATCH 16/28] [zh-cn]: update the translation of Range `startContainer` property (#23115) Co-authored-by: A1lo --- .../web/api/range/startcontainer/index.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/files/zh-cn/web/api/range/startcontainer/index.md b/files/zh-cn/web/api/range/startcontainer/index.md index 5340d651c5f598..3225037b16141f 100644 --- a/files/zh-cn/web/api/range/startcontainer/index.md +++ b/files/zh-cn/web/api/range/startcontainer/index.md @@ -1,19 +1,19 @@ --- -title: Range.startContainer +title: Range:startContainer 属性 slug: Web/API/Range/startContainer +l10n: + sourceCommit: c58e8c1dd6ecbcb63894c7dd17fb9495b9511b4e --- {{ApiRef("DOM")}} -Range.startContainer 是只读属性,返回 Range 开始的节点。要更改节点的起始位置,请使用 Range.setStart() 方法。 +**`Range.startContainer`** 只读属性返回 `Range` 开始所在的 {{domxref("Node")}}。要更改节点的起始位置,请使用 {{domxref("Range.setStart()")}} 方法。 -## Syntax +## 值 -```plain -startRangeNode = range.startContainer; -``` +{{domxref("Node")}} 对象。 -## Example +## 示例 ```js range = document.createRange(); @@ -22,14 +22,14 @@ range.setEnd(endNode, endOffset); startRangeNode = range.startContainer; ``` -## Specifications +## 规范 {{Specifications}} -## Browser compatibility +## 浏览器兼容性 {{Compat}} -## See also +## 参见 -- [The DOM interfaces index](/zh-CN/docs/DOM/DOM_Reference) +- [DOM 接口索引](/zh-CN/docs/Web/API/Document_Object_Model) From 01e7d1136e192e08a648f26ff79b91fdbcf5a709 Mon Sep 17 00:00:00 2001 From: 111111112 <70954573+mikhail-balandin@users.noreply.github.com> Date: Mon, 19 Aug 2024 02:26:23 +0500 Subject: [PATCH 17/28] [ru] improve `Web/JavaScript/Reference/Global_Objects/Array/flat` translation (#23067) * change var to const declaration according modern es standart * update examples, improve translation, remove odd sections --------- Co-authored-by: Leonid Vinogradov --- .../global_objects/array/flat/index.md | 100 ++++-------------- 1 file changed, 19 insertions(+), 81 deletions(-) diff --git a/files/ru/web/javascript/reference/global_objects/array/flat/index.md b/files/ru/web/javascript/reference/global_objects/array/flat/index.md index 7021afaf1a7e9b..88466ea7a9755d 100644 --- a/files/ru/web/javascript/reference/global_objects/array/flat/index.md +++ b/files/ru/web/javascript/reference/global_objects/array/flat/index.md @@ -5,18 +5,19 @@ slug: Web/JavaScript/Reference/Global_Objects/Array/flat {{JSRef}} -Метод **`flat()`** возвращает новый массив, в котором все элементы вложенных подмассивов были рекурсивно "подняты" на указанный уровень depth. +Метод **`flat()`** экземпляров {{jsxref("Array")}} возвращает новый массив, в котором все элементы вложенных подмассивов рекурсивно "подняты" на указанный уровень. ## Синтаксис -``` -var newArray = arr.flat(depth); +```js-nolint +flat() +flat(depth) ``` ### Параметры - `depth` {{optional_inline}} - - : На сколько уровней вложенности уменьшается мерность исходного массива. По умолчанию 1. + - : Указывает, на сколько уровней вложенности уменьшается мерность исходного массива. По умолчанию 1. ### Возвращаемое значение @@ -24,103 +25,40 @@ var newArray = arr.flat(depth); ## Примеры -### Упрощение вложенных массивов +### Уплощение вложенных массивов ```js -var arr1 = [1, 2, [3, 4]]; +const arr1 = [1, 2, [3, 4]]; arr1.flat(); // [1, 2, 3, 4] -var arr2 = [1, 2, [3, 4, [5, 6]]]; +const arr2 = [1, 2, [3, 4, [5, 6]]]; arr2.flat(); // [1, 2, 3, 4, [5, 6]] -var arr3 = [1, 2, [3, 4, [5, 6]]]; +const arr3 = [1, 2, [3, 4, [5, 6]]]; arr3.flat(2); // [1, 2, 3, 4, 5, 6] -var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]; +const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]; arr4.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ``` -### Упрощение и "дырки" в массивах +### Использование flat() для разреженных массивов -Метод flat удаляет пустые слоты из массива: +Метод `flat()` удаляет пустые слоты в массивах: ```js -var arr4 = [1, 2, , 4, 5]; -arr4.flat(); -// [1, 2, 4, 5] -``` - -## Альтернативы +const arr5 = [1, 2, , 4, 5]; +console.log(arr5.flat()); // [1, 2, 4, 5] -### `reduce` и `concat` - -```js -var arr1 = [1, 2, [3, 4]]; -arr1.flat(); - -// В одномерный массив -arr1.reduce((acc, val) => acc.concat(val), []); // [1, 2, 3, 4] - -//или -const flatSingle = (arr) => [].concat(...arr); -``` +const array = [1, , 3, ["a", , "c"]]; +console.log(array.flat()); // [ 1, 3, "a", "c" ] -```js -// Для развёртывания многомерных массивов используем рекурсию, reduce и concat -const arr = [1, 2, [3, 4, [5, 6]]]; - -function flatDeep(arr, d = 1) { - return d > 0 - ? arr.reduce( - (acc, val) => - acc.concat(Array.isArray(val) ? flatDeep(val, d - 1) : val), - [], - ) - : arr.slice(); -} - -flatDeep(arr, Infinity); -// [1, 2, 3, 4, 5, 6] -``` - -```js -//не рекурсивное упрощение с использованием стэка -var arr1 = [1, 2, 3, [1, 2, 3, 4, [2, 3, 4]]]; -function flatten(input) { - const stack = [...input]; - const res = []; - while (stack.length) { - // забираем последнее значение - const next = stack.pop(); - if (Array.isArray(next)) { - // добавляем к массиву элементы не модифицируя исходное значение - stack.push(...next); - } else { - res.push(next); - } - } - //разворачиваем массив, чтобы восстановить порядок элементов - return res.reverse(); -} -flatten(arr1); // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4] -``` - -```js -//рекурсивно упрощаем массив -function flatten(array) { - var flattend = []; - (function flat(array) { - array.forEach(function (el) { - if (Array.isArray(el)) flat(el); - else flattend.push(el); - }); - })(array); - return flattend; -} +const array2 = [1, , 3, ["a", , ["d", , "e"]]]; +console.log(array2.flat()); // [ 1, 3, "a", ["d", empty, "e"] ] +console.log(array2.flat(2)); // [ 1, 3, "a", "d", "e"] ``` ## Спецификации From 898f1673ec6af9c73295a568ae1b1e79f71e09eb Mon Sep 17 00:00:00 2001 From: MDN Web Docs GitHub Bot <108879845+mdn-bot@users.noreply.github.com> Date: Mon, 19 Aug 2024 04:29:26 +0200 Subject: [PATCH 18/28] [zh-cn] sync translated content (#23146) Co-authored-by: Allo --- files/zh-cn/_redirects.txt | 18 ++--- files/zh-cn/_wikihistory.json | 52 ++++++------- .../api/console/countreset_static/index.md | 2 +- .../console/groupcollapsed_static/index.md | 2 +- .../web/api/console/groupend_static/index.md | 2 +- files/zh-cn/web/api/console/index.md | 75 +++++++++---------- .../api/console/profileend_static/index.md | 2 +- .../web/api/console/timeend_static/index.md | 2 +- .../web/api/console/timelog_static/index.md | 2 +- .../web/api/console/timestamp_static/index.md | 2 +- 10 files changed, 79 insertions(+), 80 deletions(-) diff --git a/files/zh-cn/_redirects.txt b/files/zh-cn/_redirects.txt index e0858604e3b461..0c54d17e3181c1 100644 --- a/files/zh-cn/_redirects.txt +++ b/files/zh-cn/_redirects.txt @@ -306,7 +306,7 @@ /zh-CN/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest /zh-CN/docs/Web/API/XMLHttpRequest_API/Using_XMLHttpRequest /zh-CN/docs/DOM/console.dir /zh-CN/docs/Web/API/console/dir_static /zh-CN/docs/DOM/console.group /zh-CN/docs/Web/API/console/group_static -/zh-CN/docs/DOM/console.groupCollapsed /zh-CN/docs/Web/API/console/groupcollapsed_static +/zh-CN/docs/DOM/console.groupCollapsed /zh-CN/docs/Web/API/console/groupCollapsed_static /zh-CN/docs/DOM/console.log /zh-CN/docs/Web/API/console/log_static /zh-CN/docs/DOM/console.trace /zh-CN/docs/Web/API/console/trace_static /zh-CN/docs/DOM/document /zh-CN/docs/Web/API/Document @@ -1934,30 +1934,30 @@ /zh-CN/docs/Web/API/caches /zh-CN/docs/Web/API/Window/caches /zh-CN/docs/Web/API/console.dir /zh-CN/docs/Web/API/console/dir_static /zh-CN/docs/Web/API/console.group /zh-CN/docs/Web/API/console/group_static -/zh-CN/docs/Web/API/console.groupCollapsed /zh-CN/docs/Web/API/console/groupcollapsed_static +/zh-CN/docs/Web/API/console.groupCollapsed /zh-CN/docs/Web/API/console/groupCollapsed_static /zh-CN/docs/Web/API/console.log /zh-CN/docs/Web/API/console/log_static /zh-CN/docs/Web/API/console.time /zh-CN/docs/Web/API/console/time_static /zh-CN/docs/Web/API/console.trace /zh-CN/docs/Web/API/console/trace_static /zh-CN/docs/Web/API/console/assert /zh-CN/docs/Web/API/console/assert_static /zh-CN/docs/Web/API/console/clear /zh-CN/docs/Web/API/console/clear_static /zh-CN/docs/Web/API/console/count /zh-CN/docs/Web/API/console/count_static -/zh-CN/docs/Web/API/console/countReset /zh-CN/docs/Web/API/console/countreset_static +/zh-CN/docs/Web/API/console/countReset /zh-CN/docs/Web/API/console/countReset_static /zh-CN/docs/Web/API/console/debug /zh-CN/docs/Web/API/console/debug_static /zh-CN/docs/Web/API/console/dir /zh-CN/docs/Web/API/console/dir_static /zh-CN/docs/Web/API/console/dirxml /zh-CN/docs/Web/API/console/dirxml_static /zh-CN/docs/Web/API/console/error /zh-CN/docs/Web/API/console/error_static /zh-CN/docs/Web/API/console/group /zh-CN/docs/Web/API/console/group_static -/zh-CN/docs/Web/API/console/groupCollapsed /zh-CN/docs/Web/API/console/groupcollapsed_static -/zh-CN/docs/Web/API/console/groupEnd /zh-CN/docs/Web/API/console/groupend_static +/zh-CN/docs/Web/API/console/groupCollapsed /zh-CN/docs/Web/API/console/groupCollapsed_static +/zh-CN/docs/Web/API/console/groupEnd /zh-CN/docs/Web/API/console/groupEnd_static /zh-CN/docs/Web/API/console/info /zh-CN/docs/Web/API/console/info_static /zh-CN/docs/Web/API/console/log /zh-CN/docs/Web/API/console/log_static /zh-CN/docs/Web/API/console/profile /zh-CN/docs/Web/API/console/profile_static -/zh-CN/docs/Web/API/console/profileEnd /zh-CN/docs/Web/API/console/profileend_static +/zh-CN/docs/Web/API/console/profileEnd /zh-CN/docs/Web/API/console/profileEnd_static /zh-CN/docs/Web/API/console/table /zh-CN/docs/Web/API/console/table_static /zh-CN/docs/Web/API/console/time /zh-CN/docs/Web/API/console/time_static -/zh-CN/docs/Web/API/console/timeEnd /zh-CN/docs/Web/API/console/timeend_static -/zh-CN/docs/Web/API/console/timeLog /zh-CN/docs/Web/API/console/timelog_static -/zh-CN/docs/Web/API/console/timeStamp /zh-CN/docs/Web/API/console/timestamp_static +/zh-CN/docs/Web/API/console/timeEnd /zh-CN/docs/Web/API/console/timeEnd_static +/zh-CN/docs/Web/API/console/timeLog /zh-CN/docs/Web/API/console/timeLog_static +/zh-CN/docs/Web/API/console/timeStamp /zh-CN/docs/Web/API/console/timeStamp_static /zh-CN/docs/Web/API/console/trace /zh-CN/docs/Web/API/console/trace_static /zh-CN/docs/Web/API/console/warn /zh-CN/docs/Web/API/console/warn_static /zh-CN/docs/Web/API/crossOriginIsolated /zh-CN/docs/Web/API/Window/crossOriginIsolated diff --git a/files/zh-cn/_wikihistory.json b/files/zh-cn/_wikihistory.json index 89177063bd5841..e3d8693b45216e 100644 --- a/files/zh-cn/_wikihistory.json +++ b/files/zh-cn/_wikihistory.json @@ -16169,14 +16169,14 @@ "modified": "2020-01-12T03:19:48.000Z", "contributors": ["853419196", "ZhangKaiqiang"] }, + "Web/API/console/countReset_static": { + "modified": "2020-10-15T22:08:08.444Z", + "contributors": ["Paapaapa", "807573515"] + }, "Web/API/console/count_static": { "modified": "2019-08-15T04:00:38.089Z", "contributors": ["teemoooo", "gaowhen"] }, - "Web/API/console/countreset_static": { - "modified": "2020-10-15T22:08:08.444Z", - "contributors": ["Paapaapa", "807573515"] - }, "Web/API/console/debug_static": { "modified": "2020-10-15T22:15:26.417Z", "contributors": ["hefang"] @@ -16193,18 +16193,18 @@ "modified": "2019-08-15T04:02:05.738Z", "contributors": ["pluwen", "kameii"] }, - "Web/API/console/group_static": { - "modified": "2019-03-24T00:18:26.661Z", - "contributors": ["teoli", "khalid32", "ziyunfei"] - }, - "Web/API/console/groupcollapsed_static": { + "Web/API/console/groupCollapsed_static": { "modified": "2019-03-24T00:18:28.377Z", "contributors": ["teoli", "khalid32", "ziyunfei"] }, - "Web/API/console/groupend_static": { + "Web/API/console/groupEnd_static": { "modified": "2019-03-18T21:46:40.075Z", "contributors": ["hhxxhg", "luohe"] }, + "Web/API/console/group_static": { + "modified": "2019-03-24T00:18:26.661Z", + "contributors": ["teoli", "khalid32", "ziyunfei"] + }, "Web/API/console/info_static": { "modified": "2020-02-02T00:13:13.877Z", "contributors": ["Headog", "tsingwong", "Jaanai-Ewain", "yogoshary"] @@ -16224,18 +16224,30 @@ "ziyunfei" ] }, + "Web/API/console/profileEnd_static": { + "modified": "2020-10-15T22:04:42.916Z", + "contributors": ["JQ_Chan"] + }, "Web/API/console/profile_static": { "modified": "2019-03-18T21:41:07.871Z", "contributors": ["clwm01"] }, - "Web/API/console/profileend_static": { - "modified": "2020-10-15T22:04:42.916Z", - "contributors": ["JQ_Chan"] - }, "Web/API/console/table_static": { "modified": "2020-10-15T21:54:27.285Z", "contributors": ["RainSlide", "dondevi", "eeeeeeeason", "zzw918"] }, + "Web/API/console/timeEnd_static": { + "modified": "2020-10-15T21:50:04.648Z", + "contributors": ["luisleee", "hhxxhg", "Dcfm", "regiondavid"] + }, + "Web/API/console/timeLog_static": { + "modified": "2020-10-15T22:16:19.657Z", + "contributors": ["lifankohome", "Reaper622"] + }, + "Web/API/console/timeStamp_static": { + "modified": "2019-03-23T22:08:57.552Z", + "contributors": ["tsingwong", "ershing"] + }, "Web/API/console/time_static": { "modified": "2020-10-15T21:27:17.192Z", "contributors": [ @@ -16247,18 +16259,6 @@ "freemen" ] }, - "Web/API/console/timeend_static": { - "modified": "2020-10-15T21:50:04.648Z", - "contributors": ["luisleee", "hhxxhg", "Dcfm", "regiondavid"] - }, - "Web/API/console/timelog_static": { - "modified": "2020-10-15T22:16:19.657Z", - "contributors": ["lifankohome", "Reaper622"] - }, - "Web/API/console/timestamp_static": { - "modified": "2019-03-23T22:08:57.552Z", - "contributors": ["tsingwong", "ershing"] - }, "Web/API/console/trace_static": { "modified": "2020-10-15T21:04:54.511Z", "contributors": ["zhangchen", "airt", "teoli", "jsx", "ziyunfei"] diff --git a/files/zh-cn/web/api/console/countreset_static/index.md b/files/zh-cn/web/api/console/countreset_static/index.md index 8c63bd1629faed..645a8fb0a6e948 100644 --- a/files/zh-cn/web/api/console/countreset_static/index.md +++ b/files/zh-cn/web/api/console/countreset_static/index.md @@ -1,6 +1,6 @@ --- title: console:countReset() 静态方法 -slug: Web/API/console/countreset_static +slug: Web/API/console/countReset_static --- {{APIRef("Console API")}} diff --git a/files/zh-cn/web/api/console/groupcollapsed_static/index.md b/files/zh-cn/web/api/console/groupcollapsed_static/index.md index 3c3f39e62356dc..2f8b5483097553 100644 --- a/files/zh-cn/web/api/console/groupcollapsed_static/index.md +++ b/files/zh-cn/web/api/console/groupcollapsed_static/index.md @@ -1,6 +1,6 @@ --- title: console:groupCollapsed() 静态方法 -slug: Web/API/console/groupcollapsed_static +slug: Web/API/console/groupCollapsed_static --- {{APIRef("Console API")}} diff --git a/files/zh-cn/web/api/console/groupend_static/index.md b/files/zh-cn/web/api/console/groupend_static/index.md index 3dacb21745aafd..5cd068788fcc07 100644 --- a/files/zh-cn/web/api/console/groupend_static/index.md +++ b/files/zh-cn/web/api/console/groupend_static/index.md @@ -1,6 +1,6 @@ --- title: console:groupEnd() 静态方法 -slug: Web/API/console/groupend_static +slug: Web/API/console/groupEnd_static --- {{APIRef("Console API")}} diff --git a/files/zh-cn/web/api/console/index.md b/files/zh-cn/web/api/console/index.md index 6d151e4c6f264f..ded34799aff41d 100644 --- a/files/zh-cn/web/api/console/index.md +++ b/files/zh-cn/web/api/console/index.md @@ -3,7 +3,7 @@ title: console slug: Web/API/console --- -{{APIRef("Console API")}} +{{APIRef("Console API")}} {{AvailableInWorkers}} **`console`** 对象提供了浏览器控制台调试的接口(如:Firefox 的 [Web console](https://firefox-source-docs.mozilla.org/devtools-user/web_console/index.html))。在不同浏览器上它的工作方式可能不一样,但通常都会提供一套共性的功能。 @@ -13,19 +13,15 @@ slug: Web/API/console console.log("Failed to open the specified link"); ``` -本页面记录了 `console` 对象上的[方法](#方法)并给出了几个 [Usage](#usage) (用例)。 - -{{AvailableInWorkers}} - -## 方法 +## 实例方法 - {{domxref("console/assert_static", "console.assert()")}} - - : 如果第一个参数为 `false` ,则将消息和堆栈跟踪记录到控制台。 + - : 如果第一个参数为 `false`,则将消息和堆栈跟踪记录到控制台。 - {{domxref("console.clear_static", "console.clear()")}} - - : 清空控制台,并输出 `Console was cleared`。 + - : 清空控制台。 - {{domxref("console.count_static", "console.count()")}} - : 以参数为标识记录调用的次数,调用时在控制台打印标识以及调用次数。 -- {{domxref("console.countreset_static", "console.countReset()")}} +- {{domxref("console.countReset_static", "console.countReset()")}} - : 重置指定标签的计数器值。 - {{domxref("console.debug_static", "console.debug()")}} - : 在控制台打印一条 `"debug"` 级别的消息。 @@ -39,9 +35,9 @@ console.log("Failed to open the specified link"); - : `error()` 方法的别称。 - {{domxref("console.group_static", "console.group()")}} - : 创建一个新的内联[分组](#在_console_中使用编组), 后续所有打印内容将会以子层级的形式展示。调用 `groupEnd()`来闭合组。 -- {{domxref("console.groupcollapsed_static", "console.groupCollapsed()")}} +- {{domxref("console.groupCollapsed_static", "console.groupCollapsed()")}} - : 创建一个新的内联[分组](#在_console_中使用编组)。使用方法和 `group()` 相同,不同的是,`groupCollapsed()` 方法打印出来的内容默认是折叠的。调用`groupEnd()`来闭合组。 -- {{domxref("console.groupend_static", "console.groupEnd()")}} +- {{domxref("console.groupEnd_static", "console.groupEnd()")}} - : 闭合当前内联[分组](#在_console_中使用编组)。 - {{domxref("console.info_static", "console.info()")}} - : 打印资讯类说明信息,使用方法可以参考[使用字符串替换](#使用字符串替换)。 @@ -49,17 +45,17 @@ console.log("Failed to open the specified link"); - : 打印内容的通用方法,使用方法可以参考[使用字符串替换](#使用字符串替换)。 - {{domxref("console.profile_static", "console.profile()")}} {{Non-standard_inline}} - : Starts the browser's built-in profiler (for example, the [Firefox performance tool](https://firefox-source-docs.mozilla.org/devtools-user/performance/index.html)). You can specify an optional name for the profile. -- {{domxref("console.profileend_static", "console.profileEnd()")}} {{Non-standard_inline}} +- {{domxref("console.profileEnd_static", "console.profileEnd()")}} {{Non-standard_inline}} - : Stops the profiler. You can see the resulting profile in the browser's performance tool (for example, the [Firefox performance tool](https://firefox-source-docs.mozilla.org/devtools-user/performance/index.html)). - {{domxref("console.table_static", "console.table()")}} - : 将列表型的数据打印成表格。 - {{domxref("console.time_static", "console.time()")}} - : 启动一个以入参作为特定名称的[定时器](#定时器),在显示页面中可同时运行的定时器上限为 10,000. -- {{domxref("console.timeend_static", "console.timeEnd()")}} +- {{domxref("console.timeEnd_static", "console.timeEnd()")}} - : 结束特定的[定时器](#定时器)并以毫秒打印其从开始到结束所用的时间。 -- {{domxref("console.timelog_static", "console.timeLog()")}} +- {{domxref("console.timeLog_static", "console.timeLog()")}} - : 打印特定[定时器](#定时器)所运行的时间。 -- {{domxref("console.timestamp_static", "console.timeStamp()")}} {{Non-standard_inline}} +- {{domxref("console.timeStamp_static", "console.timeStamp()")}} {{Non-standard_inline}} - : 添加一个标记到浏览器的 [Timeline](https://developer.chrome.com/devtools/docs/timeline) 或 [Waterfall](https://profiler.firefox.com/docs/) 工具。 - {{domxref("console.trace_static", "console.trace()")}} - : 输出[堆栈跟踪](#堆栈跟踪)。 @@ -76,17 +72,17 @@ console 对象中较多使用的主要有四个方法 {{domxref("console.log_sta #### 打印单个对象 -The simplest way to use the logging methods is to output a single object: +使用日志记录方法的最简单方式是输出单个对象: ```js -var someObject = { str: "Some text", id: 5 }; +const someObject = { str: "一些文本", id: 5 }; console.log(someObject); ``` 打印结果类似下面: -``` -[09:27:13.475] ({str:"Some text", id:5}) +```plain +{str:"一些文本", id:5} ``` #### 打印多个对象 @@ -94,15 +90,15 @@ console.log(someObject); 可以打印多个对象,就像下面一样: ```js -var car = "Dodge Charger"; -var someObject = { str: "Some text", id: 5 }; -console.info("My first car was a", car, ". The object is:", someObject); +const car = "道奇战马"; +const someObject = { str: "一些文本", id: 5 }; +console.info("我的第一辆车是", car, "。该对象为:", someObject); ``` 打印结果类似下面: -``` -[09:28:22.711] My first car was a Dodge Charger . The object is: ({str:"Some text", id:5}) +```plain +我的第一辆车是 道奇战马。该对象为: {str:"一些文本", id:5} ``` #### 使用字符串替换 @@ -121,20 +117,20 @@ console.info("My first car was a", car, ". The object is:", someObject); 当要替换的参数类型和预期的打印类型不同时,参数会被转换成预期的打印类型。 -``` -for (var i=0; i<5; i++) { - console.log("Hello, %s. You've called me %d times.", "Bob", i+1); +```js +for (let i = 0; i < 5; i++) { + console.log("你好,%s。你已经联系我 %d 次了。", "小明", i + 1); } ``` 输出样例如下所示: -``` -[13:14:13.481] Hello, Bob. You've called me 1 times. -[13:14:13.483] Hello, Bob. You've called me 2 times. -[13:14:13.485] Hello, Bob. You've called me 3 times. -[13:14:13.487] Hello, Bob. You've called me 4 times. -[13:14:13.488] Hello, Bob. You've called me 5 times. +```plain +你好,小明。你已经联系我 1 次了。 +你好,小明。你已经联系我 2 次了。 +你好,小明。你已经联系我 3 次了。 +你好,小明。你已经联系我 4 次了。 +你好,小明。你已经联系我 5 次了。 ``` #### 为控制台定义样式 @@ -148,7 +144,9 @@ console.log( ); ``` -指令前的文本不会受到影响,但指令后的文本将会使用参数中声明的 CSS 样式。![](css-styling.png) +指令前的文本不会受到影响,但指令后的文本将会使用参数中声明的 CSS 样式。 + +![Firefox 控制台中添加了样式的文本](css-styling.png) `%c` 语法可用的属性如下 (至少在 Firefox 中是这样,别的浏览器会有诸多不同): @@ -171,7 +169,8 @@ console.log( - {{cssxref("word-spacing")}} 和 {{cssxref("word-break")}} - {{cssxref("writing-mode")}} -**注意**:控制台信息的默认行为与行内元素相似。为了应用 `padding`、`margin` 这类效果,你应当这样设置`display: inline-block`。 +> [!NOTE] +> 控制台信息的默认行为与行内元素相似。为了应用 `padding`、`margin` 这类效果,你应当将 `display` 属性设置为 `display: inline-block`。 ### 在 console 中使用编组 @@ -194,7 +193,7 @@ console.debug("Back to the outer level"); 执行结果: -![Demo of nested groups in Firefox console](console_groups_demo.png) +![Firefox 控制台中的嵌套编组演示](console_groups_demo.png) ### 计时器 @@ -212,7 +211,7 @@ console.timeEnd("answer time"); 这段代码将会打印需要用户关闭 alert box 的时间,打印时间到控制台上,等用户关闭第二个 alert 后,把结束时间打印到控制台。 -![timerresult.png](console-timelog.png) +![Firefox 控制台的时间记录](console-timelog.png) 注意无论在开始还是结束的时候都会打印计时器的名字。 @@ -236,7 +235,7 @@ foo(); 控制台的输出: -![](api-trace2.png) +![Firefox 控制台的堆栈跟踪](api-trace2.png) ## 规范 diff --git a/files/zh-cn/web/api/console/profileend_static/index.md b/files/zh-cn/web/api/console/profileend_static/index.md index e218cefbd2502c..029c8c5d280d30 100644 --- a/files/zh-cn/web/api/console/profileend_static/index.md +++ b/files/zh-cn/web/api/console/profileend_static/index.md @@ -1,6 +1,6 @@ --- title: console:profileEnd() 静态方法 -slug: Web/API/console/profileend_static +slug: Web/API/console/profileEnd_static --- {{APIRef("Console API")}}{{Non-standard_header}} diff --git a/files/zh-cn/web/api/console/timeend_static/index.md b/files/zh-cn/web/api/console/timeend_static/index.md index 0a71c599dd35a3..eb0cd3461e1b82 100644 --- a/files/zh-cn/web/api/console/timeend_static/index.md +++ b/files/zh-cn/web/api/console/timeend_static/index.md @@ -1,6 +1,6 @@ --- title: console:timeEnd() 静态方法 -slug: Web/API/console/timeend_static +slug: Web/API/console/timeEnd_static --- {{APIRef("Console API")}}{{Non-standard_header}} diff --git a/files/zh-cn/web/api/console/timelog_static/index.md b/files/zh-cn/web/api/console/timelog_static/index.md index 69dac303a9aefb..a848817149e691 100644 --- a/files/zh-cn/web/api/console/timelog_static/index.md +++ b/files/zh-cn/web/api/console/timelog_static/index.md @@ -1,6 +1,6 @@ --- title: console:timeLog() 静态方法 -slug: Web/API/console/timelog_static +slug: Web/API/console/timeLog_static --- {{APIRef("Console API")}} diff --git a/files/zh-cn/web/api/console/timestamp_static/index.md b/files/zh-cn/web/api/console/timestamp_static/index.md index 01dd90bca5125a..f3eec06c9bea82 100644 --- a/files/zh-cn/web/api/console/timestamp_static/index.md +++ b/files/zh-cn/web/api/console/timestamp_static/index.md @@ -1,6 +1,6 @@ --- title: console:timeStamp() 静态方法 -slug: Web/API/console/timestamp_static +slug: Web/API/console/timeStamp_static --- {{APIRef("Console API")}}{{Non-standard_header}} From bfdccd2e0ecf8ce3ab1f3d803e3a182a029fc930 Mon Sep 17 00:00:00 2001 From: Hoarfroster Date: Mon, 19 Aug 2024 10:40:15 +0800 Subject: [PATCH 19/28] zh-CN: create `action.setBadgeTextColor()` (#22968) Co-authored-by: A1lo --- .../api/action/setbadgetextcolor/index.md | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/action/setbadgetextcolor/index.md diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/action/setbadgetextcolor/index.md b/files/zh-cn/mozilla/add-ons/webextensions/api/action/setbadgetextcolor/index.md new file mode 100644 index 00000000000000..323b379376e331 --- /dev/null +++ b/files/zh-cn/mozilla/add-ons/webextensions/api/action/setbadgetextcolor/index.md @@ -0,0 +1,111 @@ +--- +title: action.setBadgeTextColor() +slug: Mozilla/Add-ons/WebExtensions/API/action/setBadgeTextColor +l10n: + sourceCommit: f6ff6e14c5af7cb9ed701d7f4506f770014c704f +--- + +{{AddonSidebar}} + +设置浏览器操作的徽章文本颜色。未指定徽章文本颜色的标签页将继承全局徽章文本颜色。 + +> [!NOTE] +> 该 API 在 Manifest V3 或更高版本中可用。 + +## 语法 + +```js-nolint +browser.action.setBadgeTextColor( + details // 对象 +) +``` + +### 参数 + +- `details` + + - : 一个含有下列属性的对象: + + - `color` + + - : 颜色,指定为一下之一: + + - 字符串:任意 CSS [\](/zh-CN/docs/Web/CSS/color_value) 值,例如 `"red"`、`"#FF0000"` 或 `"rgb(255 0 0)"`。若字符串不是一个正确的颜色,则 Promise 会被拒绝且背景颜色不会被更改。 + - `{{WebExtAPIRef('action.ColorArray')}}` 对象。 + - `null`,若指定了 `tabId`,则会移除该标签页的徽章文本颜色,让标签页继承全局徽章文本颜色;反之,会撤销对全局徽章文本颜色的修改使之变回默认取值。 + + - `tabId` {{optional_inline}} + - : `integer`,指定要设置徽章文本颜色的标签页。当用户导航到新页面的时候,文本颜色将被重置。 + - `windowId` {{optional_inline}} + - : `integer`,指定要设置徽章文本颜色的窗口。 + + + +- 若同时指定了 `windowId` 和 `tabId`,则函数出错且颜色不会被设置。 +- 若同时未指定 `windowId` 和 `tabId`,则将设置全局徽章文本颜色。 + +## 示例 + +徽章文本颜色最初设置为红色,并且当浏览器操作被单击时变为绿色: + +```js +browser.action.setBadgeText({ text: "1234" }); +browser.action.setBadgeTextColor({ color: "red" }); + +browser.action.onClicked.addListener(() => { + browser.action.setBadgeTextColor({ color: "green" }); +}); +``` + +仅为活动标签页设置徽章文本颜色: + +```js +browser.action.setBadgeText({ text: "1234" }); +browser.action.setBadgeTextColor({ color: "red" }); + +browser.action.onClicked.addListener((tab) => { + browser.action.setBadgeTextColor({ + color: "green", + tabId: tab.id, + }); +}); +``` + +{{WebExtExamples}} + +## 浏览器兼容性 + +{{Compat}} + +> [!NOTE] +> 该 API 基于 Chromium 的 [`chrome.action`](https://developer.chrome.com/docs/extensions/reference/action/#method-setBadgeBackgroundColor) API。本文衍生自 Chromium 代码中的 [`browser_action.json`](https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/browser_action.json)。 + + From bd6f8825bee37fe093c86ba96473015b2b3e48f6 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 19 Aug 2024 20:48:24 +0900 Subject: [PATCH 20/28] =?UTF-8?q?2024/08/02=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20(#23072)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 2024/08/02 時点の英語版に基づき更新 * Update files/ja/web/http/cookies/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- files/ja/web/http/cookies/index.md | 277 ++++++++++++++++------------- 1 file changed, 154 insertions(+), 123 deletions(-) diff --git a/files/ja/web/http/cookies/index.md b/files/ja/web/http/cookies/index.md index 384e0a5ef3f7ee..a8aedffa1ddaf2 100644 --- a/files/ja/web/http/cookies/index.md +++ b/files/ja/web/http/cookies/index.md @@ -2,40 +2,53 @@ title: HTTP Cookie の使用 slug: Web/HTTP/Cookies l10n: - sourceCommit: 98f4d0818bc8fbe863130b41703df069b0d816bd + sourceCommit: cb132bc83b660e51be8959de5336c00b08030104 --- {{HTTPSidebar}} -**HTTP Cookie** (ウェブ Cookie、ブラウザー Cookie) は、サーバーがユーザーのウェブブラウザーに送信する小さなデータであり、ブラウザーに保存され、その後のリクエストと共に同じサーバーへ返送されます。一般的には、 2 つのリクエストが同じブラウザーから送信されたものであるかを知るために使用されます。例えば、ユーザーのログイン状態を維持することができます。 Cookie は、[ステートレス](/ja/docs/Web/HTTP/Overview#http_はステートレスであるがセッションレスではない)な HTTP プロトコルのためにステートフルな情報を記憶します。 +**Cookie**(ウェブ Cookie、ブラウザー Cookie とも呼ぶ)は、サーバーがユーザーのウェブブラウザーに送信する小さなデータです。ブラウザーは Cookie を保存したり、新しい Cookie を作成したり、既存の Cookie を変更したり、後でリクエストされたときに同じサーバーにそれらを送り返したりすることができます。 Cookie により、ウェブアプリケーションは限られた量のデータを格納し、状態についての情報を記憶することができます。HTTP プロトコルは既定では[ステートレス](/ja/docs/Web/HTTP/Overview#http_はステートレスであるがセッションレスではない)だからです。 -Cookie は主に、以下の 3 つの用途で使用されます。 +この記事では、Cookie の主な用途を調べ、使用する際の最善の手法を説明し、プライバシーとセキュリティへの影響を見ていきます。 -- セッション管理 - - : ログイン、ショッピングカート、ゲームのスコア、またはその他のサーバーが覚えておくべきもの -- パーソナライズ - - : ユーザー設定、テーマ、その他の設定 -- トラッキング - - : ユーザーの行動の記録および分析 +## Cookie の用途 -Cookie は、クライアント側の汎用的な記憶領域として使用されたことがあります。これは他にクライアントへデータを保存する手段がなかった頃は合理的でしたが、現在では新しいストレージ API を使用することが推奨されています。 Cookie はすべてのリクエストで送信されるので、(特にモバイルデータ通信で)性能を悪化させる可能性があります。クライアントストレージ向けの新しい API として、[ウェブストレージ API](/ja/docs/Web/API/Web_Storage_API) (`localStorage` および `sessionStorage`) と [IndexedDB](/ja/docs/Web/API/IndexedDB_API) があります。 +通常、サーバーは HTTP Cookie のコンテンツを 使用して、さまざまなリクエストが同じブラウザー/ユーザーから送られたものかどうかを判断し、その後、必要に応じて個人設定または一般的なレスポンスを発行します。以下では、非常にシンプルなログインシステムについて説明します。 -> [!NOTE] -> 保存された Cookie (およびウェブページが使用できる他のストレージ) を確認するには、開発ツールの[ストレージインスペクター](https://firefox-source-docs.mozilla.org/devtools-user/storage_inspector/index.html)を有効化して、ストレージのツリーで Cookie を選択してください。 +1. ユーザーは、例えばフォーム送信により、ログイン資格情報をサーバーに送信します。 +2. 資格情報が正しい場合、サーバーはユーザーがログインしたことを示すように UI を更新し、ブラウザー上のログイン状態を記録するセッション ID を含むクッキーを返します。 +3. 後日、ユーザーは同じサイトの別のページに移動します。ブラウザーは、ユーザーがまだサインインしていると認識していることを示すために、セッション ID を含むクッキーを、対応するリクエストとともに送信します。 +4. サーバーはセッション ID をチェックし、有効であれば、ユーザーに新しいページの個人設定版を送信します。無効であれば、セッション ID は削除され、ユーザーにはページの一般版が表示されます(あるいは、「アクセスが拒否されました」というメッセージが表示され、再度サインインするよう求められる場合もあります)。 + +![上記のログインシステムの説明の視覚表現](cookie-basic-example.png) + +Cookie は、主に次の 3 つの用途で使用されます。 + +- **セッション管理**: ユーザーのログイン状態、ショッピングカート、ゲームのスコア、またはその他のユーザーセッションに関するサーバーが覚えておくべきその他のもの。 +- **パーソナライズ**: 表示言語や UI テーマのようなユーザー設定。 +- **トラッキング**: ユーザーの行動の記録および分析。 -## Cookie の作成 +### データストレージ -HTTP リクエストを受け取った後、サーバーはレスポンスで {{HTTPHeader("Set-Cookie")}} ヘッダーを送信することができます。通常 Cookie はブラウザーに保存され、また Cookie は同じサーバーに対して行われるリクエストと共に HTTP の {{HTTPHeader("Cookie")}} ヘッダーの中で送信されます。有効期限や期間を設定することができ、その後は Cookie が送信されなくなります。特定のドメインやパスへの追加の制約を設定することができ、Cookie をどこに送信するかを制限することができます。以下で言及されているヘッダー属性の詳細については、 {{HTTPHeader("Set-Cookie")}} のリファレンス記事を参照してください。 +ウェブの初めの頃、Cookie は汎用的なクライアント側データのストレージ用途に使用されていました。他に選択肢がなかったためです。より新しいストレージ API 、例えば [ウェブストレージ API](/ja/docs/Web/API/Web_Storage_API) (`localStorage` および `sessionStorage`) や [IndexedDB](/ja/docs/Web/API/IndexedDB_API) などが現在では推奨されています。 + +これらはストレージを前提に設計されており、サーバーにデータを送信することはなく、Cookie をストレージとして使用する際に生じる、次のような他の欠点もありません。 + +- ブラウザーは一般的に、ドメインごとの Cookie の最大数(ブラウザーによって異なりますが、通常は数百)と、Cookie ごとの最大サイズ(通常は 4KB)に制限されています。ストレージ APIは 、より大量のデータを格納することができます。 + Cookie はリクエストのたびに送信されるため、パフォーマンスを低下させる可能性があります(例えば、モバイルの低速データ接続の場合)。特に、多くの Cookie を設定している場合はその傾向が強くなります。 + +> [!NOTE] +> 保存された Cookie (およびウェブページが使用できる他のストレージ) を確認するには、Firefox 開発ツールの[ストレージインスペクター](https://firefox-source-docs.mozilla.org/devtools-user/storage_inspector/index.html)か、Chrome 開発者ツールの[アプリケーションパネル](https://developer.chrome.com/docs/devtools/progressive-web-apps)を利用することで実現できます。 -### `Set-Cookie` ヘッダーと `Cookie` ヘッダー +## Cookie の作成、削除、更新 -HTTP の {{HTTPHeader("Set-Cookie")}} レスポンスヘッダーは、サーバーがユーザーエージェントへ Cookie を送信するために使用します。単純な Cookie は次のように設定されます。 +HTTP リクエストを受信した後、サーバーはレスポンスに 1 つまたは複数の {{HTTPHeader("Set-Cookie")}} ヘッダーを送信することができ、それぞれのヘッダーが別個の Cookie を設定します。単純な Cookie は、次のように名前付きの値のペアを指定することで設定されます。 ```http Set-Cookie: = ``` -これは、サーバーからクライアントへ Cookie の組み合わせを保存するよう指示することを表します。 +次の HTTP レスポンスは、受信側のブラウザーに Cookie のペアを格納するように指示します。 ```http HTTP/2.0 200 OK @@ -46,7 +59,10 @@ Set-Cookie: tasty_cookie=strawberry [ページの内容] ``` -また、そのサーバーへのその後のすべてのリクエストにおいて、ブラウザーは以前格納されたすべての Cookie を、 {{HTTPHeader("Cookie")}} ヘッダーを使用してサーバーへ送信します。 +> [!NOTE] +> さまざまなサーバーサイド言語/フレームワークで `Set-Cookie` ヘッダーを使用する方法を調べてみましょう。 [PHP](https://www.php.net/manual/en/function.setcookie.php), [Node.JS](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_response_setheader_name_value), [Python](https://docs.python.org/3/library/http.cookies.html), [Ruby on Rails](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html) + +新しいリクエストが行われると、ブラウザーは通常、HTTP ヘッダー内の {{HTTPHeader("Cookie")}} で、前回格納された Cookie を現在のドメイン用にサーバーに送信します。 ```http GET /sample_page.html HTTP/2.0 @@ -54,158 +70,180 @@ Host: www.example.org Cookie: yummy_cookie=choco; tasty_cookie=strawberry ``` -> [!NOTE] -> 様々なサーバー側アプリケーションにおける `Set-Cookie` ヘッダーの使い方を紹介します。 -> -> - [PHP](https://www.php.net/manual/ja/function.setcookie.php) -> - [Node.JS](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_response_setheader_name_value) -> - [Python](https://docs.python.org/3/library/http.cookies.html) -> - [Ruby on Rails](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html) +### 削除: Cookie の持続時間の定義 + +有効期限日または期間を指定すると、それ以降は Cookie が削除され、送信されなくなります。Cookie を作成する際に {{HTTPHeader("Set-Cookie")}} ヘッダーに設定する属性に応じて、永続的 Cookie またはセッション Cookie のどちらかになります。 + +- 永続的 Cookie は、`Expires` 属性で指定された日時が過ぎると削除されます。 + + ```http + Set-Cookie: id=a3fWa; Expires=Thu, 31 Oct 2021 07:28:00 GMT; + ``` + + または、`Max-Age` 属性で指定した期間が経過した後にも削除されます。 -### Cookie の持続時間の定義 + ```http + Set-Cookie: id=a3fWa; Max-Age=2592000 + ``` -Cookie の持続時間は 2 通りの方法で定義することができます。 + > **メモ:** `Expires` は `Max-Age` よりも長い期間の指定ができますが、`Max-Age` のほうがエラーの可能性が低く、両方が設定されている場合はこちらが優先されます。この理由としては、`Expires` で日時を設定した場合、Cookie が設定されているクライアントの日時との相対値となるためです。もしサーバーが異なった日時を指定していると、エラーが発生する可能性があります。 -- _セッション_ Cookie は現在のセッションが終了すると削除されます。ブラウザーはいつ「現在のセッション」が終わったと見なすかを定義し、ブラウザーによっては再起動時に*セッションの復元*を使用することができます。そのため、結果的にセッション Cookie が無期限に持続することがあります。 -- _持続的_ Cookie は、 `Expires` 属性で指定された時刻、または `Max-Age` で指定された期間が経過した後に削除されます。 +- セッション Cookie(`Max-Age` または `Expires` 属性のない Cookie)は、現在のセッションが終了すると削除されます。ブラウザーが「現在のセッション」がいつ終わるかを定義しますし、ブラウザーによっては再起動時にセッションを復元することもあります。これにより、セッション Cookie がいつまでも有効な状態になるという問題が発生する可能性があります。 -例を示します。 + > [!NOTE] + > ユーザー認証を行うウェブサイトでは、ユーザーが認証を行うたびに、すでに存在するセッションCookieも含めて、再生成して再送信する必要があります。この手法は、サードパーティがユーザーのセッションを再利用する「セッション固定攻撃」を防ぐのに役立ちます。 + +Cookie が削除された後に Cookie を再作成するよう設計された技術がいくつかあります。これらは「ゾンビ Cookie」として知られています。これらの技術は、ユーザーの[プライバシー](#トラッキングとプライバシー)と制御の原則に違反し、[データプライバシー規制](#cookie_に関する規制)に違反する可能性があり、また、それらを使用するウェブサイトが法的責任を問われる可能性もあります。 + +### Cookie の値の更新 + +HTTP 経由で Cookie を更新するには、サーバーは既存の Cookie の名前と新しい値を指定した {{HTTPHeader("Set-Cookie")}} ヘッダーを送信します。例えば次のようにします。 ```http -Set-Cookie: id=a3fWa; Expires=Thu, 31 Oct 2021 07:28:00 GMT; +Set-Cookie: id=new-value ``` -> **メモ:** `Expires` の日付を設定した場合、設定された日時はサーバーではなく、Cookie が設定されるクライアントの日時に関連します。 +これを行う理由はいくつか考えられます。例えば、ユーザーが環境設定を更新し、アプリケーションがクライアント側データに変更を反映させたい場合などです([ウェブストレージ](/ja/docs/Web/API/Web_Storage_API)などのクライアント側ストレージメカニズムを使用して、これを行うこともできます)。 -サイトがユーザーを認証する場合、ユーザーが認証するたびに、すでに存在するセッション Cookie も含めて、セッション Cookie を再生成して再送する必要があります。この手法は、第三者がユーザーのセッションを再利用する[セッション固定攻撃](/ja/docs/Web/Security/Types_of_attacks#セッションの固定)を防ぐのに役立ちます。 +#### JavaScript からの Cookie の更新 -### Cookie へのアクセス制限 +ブラウザーでは、JavaScript を使用して {{domxref("Document.cookie")}} プロパティ、または非同期の {{domxref("Cookie_Store_API", "Cookie Store API", "", "nocode")}} を使用して新しい Cookie を作成することができます。 下記すべての例で `Document.cookie` を使用していることに注意してください。これは最も広く対応/確立されているオプションだからです。 -Cookie が安全に送信され、意図しない第三者やスクリプトからアクセスされないようにするには、 `Secure` 属性と `HttpOnly` 属性の 2 つの方法があります。 +```js +document.cookie = "yummy_cookie=choco"; +document.cookie = "tasty_cookie=strawberry"; +``` + +また、[`HttpOnly`](/ja/docs/Web/HTTP/Headers/Set-Cookie#httponly) 属性が指定されていない既存の Cookie にアクセスし、新しい値を設定することもできます(作成した `Set-Cookie` ヘッダーで指定されている場合)。 -`Secure` 属性がついた Cookie は HTTPS プロトコル上の暗号化されたリクエストでのみサーバーに送信され、安全でない HTTP では決して送信されないため、{{Glossary("MitM", "中間者")}}攻撃者が簡単にアクセスすることはできません。(URL に `http:` を含む) 安全でないサイトは、 `Secure` 属性を使用して Cookie を設定することができません。ただし、`Secure` によって Cookie 内の機密情報へのアクセスをすべて防げると思ってはいけません。例えば、クライアントのハードディスクへアクセスすることで読み取られる可能性があります。 +```js +console.log(document.cookie); +// 出力: "yummy_cookie=choco; tasty_cookie=strawberry" -`HttpOnly` 属性を持つ Cookie は、 JavaScript の {{domxref("Document.cookie")}} API にはアクセスできません。サーバーに送信されるだけです。例えば、サーバー側のセッションを持続させる Cookie は JavaScript が利用する必要はないので、 `HttpOnly` 属性をつけるべきです。この予防策は、クロスサイトスクリプティング ([XSS](/ja/docs/Web/Security/Types_of_attacks#クロスサイトスクリプティング_xss)) 攻撃を緩和するのに役立ちます。 +document.cookie = "yummy_cookie=blueberry"; + +console.log(document.cookie); +// 出力: "tasty_cookie=strawberry; yummy_cookie=blueberry" +``` -例を示します。 +セキュリティ上の理由により、リクエストを開始する際に、更新された `Cookie` ヘッダーを直接送信して Cookie 値を変更することはできません。例えば、{{domxref("Window/fetch", "fetch()")}} や {{domxref("XMLHttpRequest")}} を使用してリクエストを開始する場合は、Cookie値を変更できません。JavaScript で Cookie を変更しない方がよい理由がまだあります。例えば、Cookie を作成する際に `HttpOnly` を設定するには、[セキュリティ](#セキュリティ)の節を参照してください。 + +## セキュリティ + +Cookie に情報を格納した場合、既定ではすべての Cookie 値がエンドユーザーに表示され、変更することができます。例えば、悪意のある人物が Cookie にアクセスしたり、変更したり、本来送信されるべきではないドメインに送信したりするなど、Cookie が悪用されることは避けなければなりません。 その潜在的な影響は、アプリケーションが動作しない、あるいは奇妙な動作をするなど、わずらわしいものから、壊滅的なものまで、さまざまな範囲に及びます。 例えば、犯罪者がセッションIDを盗み、それを他人になりすましてログインしているように見せかけるCookieを設定し、その過程で銀行口座や e コマースのアカウントを制御できる可能性があります。 + +Cookie を保護する方法はいくつかあり、この節で説明します。 + +### Cookie へのアクセスをブロック + +Cookie が安全に送信され、意図しない第三者やスクリプトからアクセスされないようにするには、 `Secure` 属性と `HttpOnly` 属性の 2 つの方法があります。 ```http Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly ``` -### Cookie の送信先の定義 +- `Secure` 属性がついた Cookie は、HTTPS プロトコル上の暗号化されたリクエストでのみサーバーに送信されます。安全でない HTTP では決して送信されないため、{{Glossary("MitM", "中間者攻撃の")}}攻撃者が簡単にアクセスすることはできません。(URL に `http:` のついた)安全でないサイトは、 `Secure` 属性を使用して Cookie を設定することができません。ただし、`Secure` によって Cookie 内の機密情報へのアクセスをすべて防げると思ってはいけません。例えば、クライアントのハードディスクへアクセスすることで(また、`HttpOnly` 属性が設定されていない場合は JavaScript から)読み取られる可能性があります。 -`Domain` および `Path` 属性は、Cookie の*スコープ*、つまり Cookie を送信する対象の URL を定義します。 +- `HttpOnly` 属性を持つ Cookie は、 JavaScript の {{domxref("Document.cookie")}} API にはアクセスできません。サーバーに送信されるだけです。例えば、サーバー側のセッションを持続させる Cookie は JavaScript が利用する必要はないので、`HttpOnly` 属性をつけるべきです。この予防策は、クロスサイトスクリプティング([XSS](/ja/docs/Web/Security/Types_of_attacks#クロスサイトスクリプティング_xss))攻撃を緩和するのに役立ちます。 -#### Domain 属性 +> [!NOTE] +> アプリケーションによっては、機密情報を直接 Cookie に格納するのではなく、サーバーが照合する不透明な識別子を使用したり、[JSON Web Tokens](https://jwt.io/) などの代替の認証/機密性メカニズムを調べたりしたほうがいいかもしれません。 -`Domain` 属性は、Cookie を受信することができるホストを指定します。サーバーが `Domain` を指定しなかった場合、ブラウザーは既定でドメインを Cookie を設定したのと同じ{{Glossary("host", "ホスト")}}とし、_サブドメインは除外します_。 `Domain` が指定された場合、サブドメインは常に含まれます。したがって、 `Domain` を指定すると省略時よりも制限が緩和されます。ただし、サブドメイン間でユーザーに関する情報を共有する場合は有用になるでしょう。 +### Cookie の送信先の定義 -例えば、`Domain=mozilla.org` を設定すると、`developer.mozilla.org` のようなサブドメインも含まれます。 +`Domain` および `Path` 属性は、Cookie の「スコープ」、つまり Cookie を送信する対象の URL を定義します。 -#### Path 属性 +- `Domain` 属性は、Cookie を受信することができるサーバーを指定します。指定された場合、指定されたサーバーとサブドメインで Cookie が利用できます。例えば、`mozilla.org` から `Domain=mozilla.org` を設定すると、`developer.mozilla.org` のようなサブドメインも含めて、そのドメインで Cookie が利用できるようになります。 -`Path` 属性は、 `Cookie` ヘッダーを送信するためにリクエストされた URL の中に含む必要がある URL のパスを示します。 `%x2F` ("/") の文字はディレクトリー区切り文字として解釈され、サブディレクトリーにも同様に一致します。 + ```http + Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly; Domain=mozilla.org + ``` -例えば、`Path=/docs` を設定すると、以下のリクエストパスに一致します。 + `Set-Cookie` ヘッダーで `Domain` 属性が指定されていない場合、Cookie はそれを設定したサーバーでは利用できますが、そのサブドメインでは利用できません。そのため、`Domain` を指定することは、それを除外するよりも制限が少なくなります。 + サーバーが `Domain` 属性を設定できるのは自分自身で管理するドメイン、または親ドメインのみであり、サブドメインや他にもドメインには設定できないことに注意してください。 + 例えば、ドメインが `foo.example.com` のサーバーは、この属性を `example.com` または `foo.example.com` に設定することはできますが、`bar.foo.example.com` や `elsewhere.com` には設定できません(ただし、`bar.foo.example.com` などのサブドメインには Cookie が送信されます)。 + 詳細は[不正なドメイン](/ja/docs/Web/HTTP/Headers/Set-Cookie#不正なドメイン)を参照してください。 -- `/docs` -- `/docs/` -- `/docs/Web/` -- `/docs/Web/HTTP` +- `Path` 属性は、 `Cookie` ヘッダーを送信するためにリクエストされた URL の中に含む必要がある URL のパスを示します。 -ただし、これらのリクエストパスには一致しません。 + ```http + Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly; Path=/docs + ``` -- `/` -- `/docsets` -- `/fr/docs` + `%x2F` ("/") の文字はディレクトリー区切り文字として解釈され、サブディレクトリーにも同様に一致します。例えば、`Path=/docs` を設定すると、以下のリクエストパスに一致します。 -#### SameSite 属性 + - `/docs` + - `/docs/` + - `/docs/Web/` + - `/docs/Web/HTTP` -`SameSite` 属性により、サーバーがサイト間リクエスト (ここで{{Glossary("Site", "サイト")}}は登録可能なドメインによって定義されます) と一緒に Cookie を送るべきではないことを要求することができます。これは、クロスサイトリクエストフォージェリー攻撃 ({{Glossary("CSRF")}}) に対していくらかの防御となります。取ることができる値は `Strict`, `Lax`, `None` の 3 つです。 + ただし、これらのリクエストパスには一致しません。 -`Strict` では、ブラウザーは Cookie の元サイトからのリクエストに対してのみ Cookie を送ります。 -`Lax` も同様ですが、ユーザーが Cookie の元サイトに移動したときに(たとえユーザーが異なる形のサイトから来たとしても)ブラウザーは Cookie を送信します。 -例えば、外部サイトからリンクをたどった場合です。 `None` は Cookie を発生元サイトへリクエストとサイト間のリクエストの両方で送信されますが、*安全なコンテキスト*でのみ送信されます(つまり、 `SameSite=None`なら `Secure` 属性も設定する必要があります)。 -もし `SameSite` 属性が設定されていない場合、 Cookie は `Lax` として扱われます。 + - `/` + - `/docsets` + - `/fr/docs` -次に例を示します。 +#### `SameSite` 属性によるサードパーティ Cookie の制御 -```http -Set-Cookie: mykey=myvalue; SameSite=Strict -``` +[`SameSite`](/ja/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value) 属性は、サーバーがサイト間リクエストとともに Cookie を送信するかどうか、すなわちサードパーティ Cookie を送信するかどうかを指定します。サイト間リクエストとは、{{Glossary("Site", "サイト")}}(登録されているドメイン)やスキーム(http または https)がユーザーが現在いるサイトと一致しないリクエストのことです。これには、他のサイト上のリンクがクリックされて自分のサイトに移動する際に送信されるリクエストや、埋め込みサードパーティコンテンツによって送信されるリクエストが含まれます。 -> **メモ:** `SameSite` に関する標準規格が最近変更されました(MDN で文書化している上記の動作は新しい動作です)。 -> ブラウザーの特定の版がこの属性をどのように扱うかの情報については、 Cookie の[ブラウザー互換性](/ja/docs/Web/HTTP/Headers/Set-Cookie/SameSite#ブラウザーの互換性)一覧表を参照してください。 -> -> - `SameSite=Lax` は `SameSite` が指定されなかった場合の新しい既定値です。 -> 以前は、 Cookie は既定ですべてのリクエストに送信されていました。 -> - Cookie に `SameSite=None` が付いた場合は、 `Secure` 属性も指定することになりました(安全なコンテキストが必要になりました)。 -> - 同じドメインの Cookie であっても、異なるスキーム (`http:` か `https:` か) を使用して送信された場合は同じサイトと見なされなくなりました。 +`SameSite` は、情報の漏洩を防止し、ユーザーの[プライバシー](#プライバシーと追跡)を保護し、{{Glossary("CSRF", "クロスサイトリクエストフォージェリー")}}攻撃に対していくらかの防御となります。取ることができる値は `Strict`, `Lax`, `None` の 3 つです。 -#### Cookie の接頭辞 +- `Strict` は、ブラウザーが Cookie の発行元サイトからのリクエストに対してのみ、レスポンスで Cookie を送信するようにします。これは、認証やショッピングカート情報の格納など、常に最初のナビゲーションの後に来る機能に関連する Cookie がある場合に使用すべきです。 -Cookie の仕組みの設計では、 Cookie が安全なオリジンに設定されているかどうか、 Cookie が当初は*どこに*設定されたのかをサーバーが確認することができないようになっています。 + ```http + Set-Cookie: cart=110045_77895_53420; SameSite=Strict + ``` -サブドメイン上にある脆弱性のあるアプリケーションが `Domain` 属性を使用して Cookie を設定すると、ほかのすべてのサブドメインで Cookie にアクセスできるようにすることができます。この仕組みは*セッション固定*攻撃で悪用される可能性があります。主な対策方法は[セッション固定化](/ja/docs/Web/Security/Types_of_attacks#セッションの固定)を参照してください。 + > [!NOTE] + > 機密情報を使用する Cookie は、[有効期限](#削除_cookie_の持続時間の定義)も短く指定しましょう。 -しかし、[多層防御]()として、 Cookie に関する特定の事実を主張するために *Cookie の接頭辞*を使うことが可能です。以下の 2 つの接頭辞が利用可能です。 +- `Lax` も同様ですが、ユーザーが Cookie の発行元サイトに移動(ユーザーが別のサイトから移動してくる場合でも)した際にも、ブラウザーが Cookie を送信します。これは、サイトの表示に影響を与える Cookie に役立ちます。例えば、ウェブサイトにアフィリエイトリンク付きの提携製品情報を持たせることができます。そのリンクで提携サイトに移動すると、アフィリエイトリンクを辿ったことを示す Cookie を設定し、報酬バナーを表示したり、製品購入時に割引を指定したりすることができます。 -- `__Host-` - - : Cookie 名にこの接頭辞がついている場合、 {{HTTPHeader("Set-Cookie")}} ヘッダーが受け入れられるのは `Secure` 属性で指定されており、安全なオリジンから送信されており、 `Domain` 属性を含んで*おらず*、 `Path` 属性が `/` に設定されている場合のみです。この場合、これらの Cookie は「ドメインにロックされている」と見なすことができます。 -- `__Secure-` - - : Cookie 名にこの接頭辞がある場合、 {{HTTPHeader("Set-Cookie")}} ディレクティブが受け入れられるのは、 `Secure` であり、安全なオリジンから送信されている場合のみです。これは `__Host-` 接頭辞よりも弱いものです。 + ```http + Set-Cookie: affiliate=e4rt45dw; SameSite=Lax + ``` -これらの接頭辞が付いていて、制約に適合していない Cookie は、送られてもブラウザーが拒否します。これにより、仮にサブドメインで接頭辞の付いた Cookie を作成した場合、サブドメインに限定されるか、完全に無視されるかします。アプリケーションサーバーは、ユーザーが認証されているか、あるいは CSRF トークンが正しいかどうかを判断するときに、特定の Cookie 名をチェックするだけなので、これはセッションの固定化に対する防御手段として効果的に機能します。 +- `None` は、Cookie が元のサイトとサイト間のリクエストの両方で送信されることを指定します。これは、例えば広告技術や分析ツールのプロバイダーなど、他のサイトに埋め込まれたサードパーティのコンテンツから送信されたリクエストとともに Cookie を送信したい場合に便利です。`SameSite=None` が設定されている場合、`Secure` 属性も設定する必要があることに注意してください。`SameSite=None` では、安全なコンテキストが要求されます。 -> [!NOTE] -> アプリケーションサーバ上では、ウェブアプリケーションは接頭辞を含む完全な Cookie 名をチェック*しなければなりません*。—ユーザーエージェントは、リクエストの {{HTTPHeader("Cookie")}} ヘッダーを送信する前に Cookie から接頭辞を削除*しません*。 + ```http + Set-Cookie: widget_session=7yjgj57e4n3d; SameSite=None; Secure; HttpOnly + ``` -Cookie の接頭辞とブラウザー対応の現在の状態については、 [Set-Cookie リファレンス記事の接頭辞の節](/ja/docs/Web/HTTP/Headers/Set-Cookie#クッキーの接頭辞)を参照してください。 +もし `SameSite` 属性が設定されていない場合、 Cookie は既定で `Lax` として扱われます。 -#### JavaScript での Document.cookies を使用したアクセス +#### Cookie の接頭辞 -{{domxref("Document.cookie")}} プロパティを使用して新しい Cookie を作成することができますし、 `HttpOnly` フラグが設定されていない限り、既存の Cookie に JavaScript からアクセスすることもできます。 +Cookie の仕組みの設計上、サーバーは、Cookie が安全なオリジンから設定されたことを確認することはできず、Cookie が元々どこで設定されたのかを見分けることさえできません。 -```js -document.cookie = "yummy_cookie=choco"; -document.cookie = "tasty_cookie=strawberry"; -console.log(document.cookie); -// "yummy_cookie=choco; tasty_cookie=strawberry" とログ出力 -``` +サブドメイン上にある脆弱性のあるアプリケーションが `Domain` 属性を使用して Cookie を設定すると、ほかのすべてのサブドメインで Cookie にアクセスできるようにすることができます。この仕組みは「セッション固定攻撃」で悪用される可能性があります。主な対策方法は[セッション固定化](/ja/docs/Web/Security/Types_of_attacks#セッションの固定)を参照してください。 -JavaScript で生成された Cookie は `HttpOnly` フラグを含むことができません。 +[多層防御]()として、Cookie の接頭辞を使用することで、Cookie に関する特定の事実を主張することが可能です。以下の 2 つの接頭辞が利用可能です。 -後述する[セキュリティ](#セキュリティ)の節に記載したとおり、セキュリティの影響に注意してください。JavaScript で使用できる Cookie は、XSS によって盗まれる可能性があります。 +- `__Host-`: Cookie 名にこの接頭辞がついている場合、 {{HTTPHeader("Set-Cookie")}} ヘッダーが受け入れられるのは `Secure` 属性で指定されており、安全なオリジンから送信されており、 `Domain` 属性を含んで*おらず*、 `Path` 属性が `/` に設定されている場合のみです。この場合、これらの Cookie は「ドメインにロックされている」と見なすことができます。 +- `__Secure-`: Cookie 名にこの接頭辞がある場合、 {{HTTPHeader("Set-Cookie")}} ディレクティブが受け入れられるのは、 `Secure` であり、安全なオリジンから送信されている場合のみです。これは `__Host-` 接頭辞よりも弱いものです。 -## セキュリティ +これらの接頭辞が付いていて、制約に適合していない Cookie は、送られてもブラウザーが拒否します。これにより、仮にサブドメインで接頭辞の付いた Cookie を作成した場合、サブドメインに限定されるか、完全に無視されるかします。アプリケーションサーバーは、ユーザーが認証されているか、あるいは CSRF トークンが正しいかどうかを判断するときに、特定の Cookie 名をチェックするだけなので、これはセッションの固定化に対する防御手段として効果的に機能します。 > [!NOTE] -> 情報を Cookie に保存するときは、すべての Cookie の値がエンドユーザーから見え、変更できることを理解しておいてください。アプリケーションによっては、サーバー側で検索される不透明な識別子を使用するか、 JSON ウェブトークンのような代替の認証/機密性メカニズムを調べたほうが良いかもしれません。 +> アプリケーションサーバー上では、ウェブアプリケーションは接頭辞を含む完全な Cookie 名をチェック*しなければなりません*。ユーザーエージェントは、リクエストの {{HTTPHeader("Cookie")}} ヘッダーを送信する前に Cookie から接頭辞を削除しません。 -Cookie への攻撃を緩和する方法には次のようなものがあります。 +Cookie の接頭辞とブラウザー対応の現在の状態については、 [Set-Cookie リファレンス記事の接頭辞の節](/ja/docs/Web/HTTP/Headers/Set-Cookie# Cookie の接頭辞)を参照してください。 -- `HttpOnly` 属性を使用して、 JavaScript から Cookie の値にアクセスすることを防ぎます。 -- 機密情報 (認証を示す場合など) のために使用された Cookie は、持続時間を短く、 `SameSite` 属性を `Strict` または `Lax` に設定してください。 (上記の [SameSite Cookie](#samesite_属性) を参照。) [SameSite に対応しているブラウザー](/ja/docs/Web/HTTP/Headers/Set-Cookie#ブラウザーの互換性)では、これは、認証 Cookie がオリジン間リクエストと一緒に送信されないようにする効果があるので、そのようなリクエストはそのアプリケーションサーバーに対して事実上認証されていないことになります。 +## プライバシーとトラッキング -## トラッキングとプライバシー +先ほど、サードパーティ Cookie が送信されるタイミングを制御できる `SameSite` 属性についてお話しし、この属性がユーザーのプライバシーに役立つことを説明しました。プライバシーは、ウェブサイトを構築する上で非常に重要な考慮事項です。正しく行えば、ユーザーとの信頼関係を構築することができます。しかし、間違った方法で行うと、信頼関係を完全に損ない、他にもさまざまな問題を引き起こす可能性があります。 -### サードパーティの Cookie +サードパーティ Cookie は、{{htmlelement("iframe")}} を使用してサイトに埋め込まれたサードパーティコンテンツによって設定することができます。 サードパーティ Cookie には、ユーザープロファイル情報の共有、広告表示回数のカウント、または関連の異なるドメインにわたる分析情報の集合など、正当な用途が数多くあります。 -Cookie はドメインとスキーム(`http` や `https` など)に関連付けられ、 {{HTTPHeader("Set-Cookie")}} の `Domain` 属性が設定された場合はサブドメインにも関連付けられます。 -Cookie のドメインとスキームが現在のページと一致している場合、その Cookie はこのページと同じサイトからのものと見なされ、_ファーストパーティ Cookie_ と呼ばれます。 +しかし、サードパーティ Cookie の使い方によっては、不快で押しつけがましいユーザー体験になることもあります。サードパーティのサーバーが、複数のサイトにアクセスする際に同じブラウザーから送信された Cookie に基づいて、ユーザーの閲覧履歴や習慣に関するプロファイルを作成することができます。例えば、あるサイトで製品情報を検索したところ、その後、どこにアクセスしても類似した製品の広告がウェブ上で表示される、というようなケースがこれに該当します。 -ドメインとスキームが異なる場合、その Cookie は同じサイトのものとはみなされず、_サードパーティ Cookie_ と呼ばれます。 -ウェブページをホスティングしているサーバーがファーストパーティ Cookie を設定する一方で、ページには他のドメインのサーバーに保存されている画像やその他のコンポーネント (例えば、広告バナー) が含まれている場合があり、サードパーティ Cookie を設定することがあります。 -これらは主にウェブ上での広告やトラッキングに使用されます。 -例えば [Google が使用している Cookie の種類](https://policies.google.com/technologies/types)を参照してください。 +ブラウザーのベンダーは、ユーザーがこのような動作を好まないことを知っており、その結果、サードパーティ Cookie を既定ではすべてブロックする、あるいは少なくともその方向で計画を進めています。サードパーティ Cookie (または単にトラッキング Cookie)は、その他のブラウザーの設定や拡張機能でブロックすることができます。 -サードパーティのサーバーは、複数のサイトにアクセスした際に同じブラウザーから送信された Cookie に基づいて、ユーザーの閲覧履歴や習慣のプロファイルを構築することができます。 Firefox は既定で、トラッカーを含むことが知られているサードパーティの Cookie をブロックします。サードパーティの Cookie (またはトラッキング Cookie ) は、他のブラウザーの設定や拡張機能によってもブロックされる場合があります。 Cookie をブロックすると、一部のサードパーティ製コンポーネント (ソーシャルメディアウィジェットなど) が意図した通りに機能しなくなることがあります。 - -ユーザーのプライバシーを尊重し、サードパーティの追跡を最小限に抑えたい開発者にとって、有益な機能がいくつか使用されています。 +> [!NOTE] +> Cookie をブロックすると、サードパーティの部品(ソーシャルメディアウィジェットなど)が意図通りに機能しなくなる場合が発生します。ブラウザーがサードパーティ Cookie にさらに制限を課すため、開発者はサードパーティ Cookie への依存を縮小する方法を検討し始める必要があります。 -- サーバーは Cookie の [SameSite 属性](/ja/docs/Web/HTTP/Headers/Set-Cookie/SameSite)を設定することで、サードパーティーの Cookie を送るかどうか指定することができます(そしてそうすべきです)。 -- [Cookies Having Independent Partitioned State (CHIPS)](/ja/docs/Web/Privacy/Partitioned_cookies) は、開発者が、最上位のサイトごとに別個の Cookie ジャーを持つ、分割されたストレージへの Cookie のオプトインができるようにします。これは、サードパーティのトラッキングに Cookie を使用することを許可しないブラウザーで、サードパーティの Cookie の有効な非トラッキング用途が引き続き動作するようにするものです。 +サードパーティ Cookie のより詳しい情報、それに関連する課題、利用できる代替策については、[サードパーティ Cookie](/ja/docs/Web/Privacy/Third-party_cookies) の記事を参照してください。プライバシー全般に関するより詳しい情報は、[プライバシー](/ja/docs/Web/Privacy)のランディングページをご覧ください。 ### Cookie に関する規制 @@ -225,20 +263,13 @@ Cookie の使用を対象とした法規制には、以下のようなものが 地域によっては、他にも Cookie の使用を管理する規制があるかもしれません。これらの規制を理解し遵守することは、自分自身の責任となります。これらの規制を遵守するのに役立つ「Cookie 禁止」コードを提供している会社もあります。 -## ブラウザーに情報を格納する他の方法 - -ブラウザーにデータを保存する別のアプローチとして、 [Web Storage API](/ja/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API) があります。 [window.sessionStorage](/ja/docs/Web/API/Window/sessionStorage) と [window.localStorage](/ja/docs/Web/API/Window/localStorage) プロパティはセッション Cookie と持続的 Cookie に対応していますが、ストレージの容量制限が Cookie より大きく、サーバーに送信されることはありません。より構造化された大量のデータは、 [IndexedDB API](/ja/docs/Web/API/IndexedDB_API) またはその上に構築されたライブラリを使用して保存することができます。 - -「ゾンビ」 Cookie と呼ばれる、 Cookie が削除された後に再作成されるようにするための他の技術が作成されています。これらの技術は、ユーザーのプライバシーとユーザー制御の原則に違反し、データプライバシー規制に違反する可能性があり、これらの技術を使用しているウェブサイトが法的責任にさらされる可能性があります。 +> [!NOTE] +> 企業は、自社サイトで使用するCookieの種類を、透明性を高めるため、また規制を遵守するために開示すべきです。例えば、[Google が使用する Cookie の種類に関する通知](https://policies.google.com/technologies/cookies#types-of-cookies)や Mozilla の[ウェブサイト、コミュニケーション、Cookie のプライバシーに関する通知](https://www.mozilla.org/en-US/privacy/websites/#cookies)をご覧ください。 ## 関連情報 -- {{HTTPHeader("Set-Cookie")}} -- {{HTTPHeader("Cookie")}} -- {{domxref("Document.cookie")}} -- {{domxref("Navigator.cookieEnabled")}} -- [SameSite Cookie](/ja/docs/Web/HTTP/Headers/Set-Cookie/SameSite) -- [ストレージインスペクターを使った Cookie の調査](https://firefox-source-docs.mozilla.org/devtools-user/storage_inspector/index.html) +- 関連する HTTP ヘッダー: {{HTTPHeader("Set-Cookie")}}, {{HTTPHeader("Cookie")}} +- 関連する JavaScript API: {{domxref("Document.cookie")}}, {{domxref("Navigator.cookieEnabled")}}, {{domxref("Cookie_Store_API", "クッキーストア API", "", "nocode")}} +- [サードパーティ Cookie](/ja/docs/Web/Privacy/Third-party_cookies) - [Cookie specification: RFC 6265](https://datatracker.ietf.org/doc/html/rfc6265) -- [HTTP cookie on Wikipedia](https://en.wikipedia.org/wiki/HTTP_cookie) - [Cookies, the GDPR, and the ePrivacy Directive](https://gdpr.eu/cookies/) From b04d6f3c584bb9c836163673afcaa3fcd675daa7 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 19 Aug 2024 20:48:56 +0900 Subject: [PATCH 21/28] =?UTF-8?q?2024/08/09=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20(#23074)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 2024/08/09 時点の英語版に基づき更新 * Update files/ja/mdn/writing_guidelines/writing_style_guide/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../writing_style_guide/index.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/files/ja/mdn/writing_guidelines/writing_style_guide/index.md b/files/ja/mdn/writing_guidelines/writing_style_guide/index.md index bdab328ef493ba..6247b14938cdda 100644 --- a/files/ja/mdn/writing_guidelines/writing_style_guide/index.md +++ b/files/ja/mdn/writing_guidelines/writing_style_guide/index.md @@ -2,7 +2,7 @@ title: 執筆スタイルガイド slug: MDN/Writing_guidelines/Writing_style_guide l10n: - sourceCommit: e60194342c9666ad8a2e6e5e6c25705fe818bcde + sourceCommit: 4ecbac9e89961a132c1e7f5493ec94f60dcb1ee4 --- {{MDNSidebar}} @@ -160,9 +160,11 @@ MDN Web Docs で書くことの第一の目標は、常にオープンなウェ - **例を追加する**。すべての引数、あるいは少なくとも初級から中級レベルのユーザーが使用する可能性のある引数(またはプロパティや属性)と、追加の説明が必要な高度な引数を網羅した例を用意する必要があります。それぞれの例の前には、その例が何をするのか、それを理解するためにはどのような知識が必要なのかなどの概要を示す必要があります。例の後(または例の一部の間)には、コードがどのように動作するかを説明する文章が必要です。例の詳細やエラー処理についても手を抜いてはいけません。読者は例をコピー&ペーストして自分のプロジェクトで使用するでしょうから、そのコードが本番サイトで使用されることになるでしょう。より有用な情報は、[サンプルコードのガイドライン](/ja/docs/MDN/Writing_guidelines/Writing_style_guide/Code_style_guide)を参照してください。 - **使用例を説明する**。説明されている機能について、特に一般的な使用例がある場合は、それについて話してください。一般的な開発上の問題を解決するために文書化された方法を読者が理解すると仮定するのではなく、実際にその利用例についての節を追加し、例とその例がどのように機能するかを説明するテキストを追加してください。 - **画像情報を追加する**。すべての画像や図に適切な [`alt`](/ja/docs/Web/HTML/Element/img#alt) テキストを入れてください。このテキストは、表などのキャプションと同様に重要です。スパイダーは画像をクロールすることができないため、 [`alt`](/ja/docs/Web/HTML/Element/img#alt) テキストによって、埋め込まれたメディアに含まれるコンテンツを検索エンジンのクローラーに伝えることができます。 + > [!NOTE] > 検索エンジンのランキングを操作するために、キーワードを入れすぎたり、関係のないキーワードを使ったりすることは、良い慣習ではありません。このような行為は発見されやすく、罰せられる傾向にあります。 > 同様に、ページのサイズや検索順位を上げるために、反復的で役に立たない内容や、キーワードの塊を実際のページ内に追加するようなことも**しないでください**。これは、コンテンツの読みやすさと検索結果の両方に悪影響を及ぼします。 + - **トピックの内容を重視する**。特定のキーワードではなく、記事のトピックに沿ってコンテンツを書く方がはるかに良いことです。実際、多くの SEO 担当者は、記事の長さに応じて 5 ~ 100 種類のキーワード(ショートテール、ミディアムテール、ロングテール)をリストアップし、記事に含めるようにしています。そうすることで、表現が多様化し、繰り返しが少なくなります。 ## 執筆スタイル @@ -443,7 +445,7 @@ MDN で他のページやページの節のタイトルで参照する場合、 リンク先の節が同じページにある場合は、「上記」 (above) や「下記」 (below) の言葉を用いて、その節の場所を示唆することができます。 -- **正**: この概念は下記の[アクセシビリティの考慮](/ja/docs/Web/CSS/gradient/repeating-conic-gradient#accessibility_concerns)の節で詳しく説明しています。 +- **正**: この概念は下記の[アクセシビリティ](/ja/docs/Web/CSS/gradient/repeating-conic-gradient#アクセシビリティ)の節で詳しく説明しています。 文章の一部を記事や記事の節にリンクすることができます。リンクテキストとして説明的な語句を使用し、リンクされているページに十分なコンテキストを提供するように注意してください。 @@ -519,7 +521,7 @@ markdown の見出しレベルをスキップすることなく、小さい順 ページ内に画像やその他のメディアを載せる場合は、以下のガイドラインに従ってください。 -- メディアのライセンスが使用することを許可していることを確認してください。 [CC0](https://creativecommons.org/share-your-work/public-domain/cc0/) のようなとても寛容なライセンスを有するメディア、または少なくとも私たちの一般的なコンテンツライセンス - [クリエイティブ・コモンズ - 表示・継承ライセンス](https://creativecommons.org/licenses/by-sa/2.5/) (CC-BY-SA) と互換性のあるものを使用するようにしましょう。 +- メディアのライセンスが使用することを許可していることを確認してください。 [CC0](https://creativecommons.org/public-domain/cc0/) のようなとても寛容なライセンスを有するメディア、または少なくとも私たちの一般的なコンテンツライセンス - [クリエイティブ・コモンズ - 表示・継承ライセンス](https://creativecommons.org/licenses/by-sa/2.5/) (CC-BY-SA) と互換性のあるものを使用するようにしましょう。 - 画像の場合、 または を通すとページが軽量化されます。 - `SVG` の場合は、 [SVGOMG](https://jakearchibald.github.io/svgomg/) を通してコードを実行し、 `SVG` ファイルの最後に空行があることを確認してください。 - すべての画像に[説明的な `alt` テキストを入れる](/ja/docs/MDN/Writing_guidelines/Howto/Images_media#画像に代替テキストを追加)必要があります。 @@ -670,16 +672,15 @@ MDN Web Docs 全体の一貫性を保つため、関連情報の節を追加ま ### おすすめのスタイルガイド -ここで取り扱われていない用法とスタイルについて疑問があれば、 [Microsoft Writing Style Guide](https://docs.microsoft.com/style-guide/welcome/) を、それでもダメなら [Chicago Manual of Style](https://www.chicagomanualofstyle.org) を参照してください。 -[非公式の crib sheet for the Chicago Manual of Style](https://faculty.cascadia.edu/cma/HIST148/cmscrib.pdf) がオンラインで利用できます。 +ここで取り扱われていない用法とスタイルについて疑問があれば、 [Microsoft Writing Style Guide](https://learn.microsoft.com/en-us/style-guide/welcome/) を、それでもダメなら [Chicago Manual of Style](https://www.chicagomanualofstyle.org) を参照してください。 ### 言語、文法、綴り 記事の執筆と編集スキルを磨きたければ、以下のリソースが役立つことでしょう。(英語の情報) - [Common errors in English usage](https://brians.wsu.edu/common-errors-in-english-usage/) on brians.wsu.edu -- [English grammar FAQ](https://www-personal.umich.edu/~jlawler/aue.html) on alt-usage-english.org +- [English grammar FAQ](https://websites.umich.edu/~jlawler/aue.html) on alt-usage-english.org - [English language and usage](https://english.stackexchange.com/) on english.stackexchange.com: Question and answer site for English language usage -- [Merriam-Webster's Concise Dictionary of English Usage](https://www.google.com/books/edition/Merriam_Webster_s_Dictionary_of_English/UDIjAQAAIAAJ) on google.com/books (published 2002): Scholarly but user-friendly, evidence-based advice; very good for non-native speakers, especially for preposition usage +- [Merriam-Webster's Concise Dictionary of English Usage](https://books.google.com/books?id=UDIjAQAAIAAJ) on google.com/books (published 2002): Scholarly but user-friendly, evidence-based advice; very good for non-native speakers, especially for preposition usage - [On Writing Well](https://www.harpercollins.com/products/on-writing-well-william-zinsser) by William Zinsser on harpercollins.com (published 2016) -- [Style: Lessons in Clarity and Grace](https://www.google.ca/books/edition/Style/QjskvgEACAAJ) by Joseph Williams and Gregory Colomb on google.com/books (published 2019) +- [Style: Lessons in Clarity and Grace](https://books.google.com/books?id=QjskvgEACAAJ) by Joseph Williams and Gregory Colomb on google.com/books (published 2019) From a58c3eb116ba625679b635ed452a3568d46b42cd Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 19 Aug 2024 20:49:49 +0900 Subject: [PATCH 22/28] =?UTF-8?q?2024/07/27=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20(#23075)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 2024/07/27 時点の英語版に基づき更新 * Update files/ja/web/api/serviceworkerglobalscope/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../web/api/serviceworkerglobalscope/index.md | 62 ++++++++++++------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/files/ja/web/api/serviceworkerglobalscope/index.md b/files/ja/web/api/serviceworkerglobalscope/index.md index bf6dd536ce7b52..ce27c90087d0ae 100644 --- a/files/ja/web/api/serviceworkerglobalscope/index.md +++ b/files/ja/web/api/serviceworkerglobalscope/index.md @@ -2,10 +2,10 @@ title: ServiceWorkerGlobalScope slug: Web/API/ServiceWorkerGlobalScope l10n: - sourceCommit: 6d194a9afcce7beef0082c1dc50644bd0fcda635 + sourceCommit: c29cee3dcb0d0e66093dd0c18aa82e0eab9d6d14 --- -{{APIRef("Service Workers API")}} +{{APIRef("Service Workers API")}}{{SecureContext_Header}}{{AvailableInWorkers("service")}} **`ServiceWorkerGlobalScope`** は[サービスワーカー API](/ja/docs/Web/API/Service_Worker_API) のインターフェイスで、サービスワーカーのグローバル実行コンテキストを表します。 @@ -13,7 +13,7 @@ l10n: いったん正しく登録されたら、サービスワーカーはメモリーとプロセッサーの力を温存するため、アイドル時であれば停止させることができます。アクティブなサービスワーカーは、例えば {{domxref("ServiceWorkerGlobalScope.fetch_event", "fetch")}} や {{domxref("ServiceWorkerGlobalScope.message_event", "message")}} などのイベントに応じて自動的に再起動します。 -加えて、同期リクエストはサービスワーカーでは許可されていません。非同期リクエスト、つまり {{domxref("fetch()")}} メソッド経由で初期化されたものが使われます。 +加えて、同期リクエストはサービスワーカーでは許可されていません。非同期リクエスト、つまり {{domxref("WorkerGlobalScope/fetch", "fetch()")}} メソッド経由で初期化されたものが使われます。 このインターフェイスは {{domxref("WorkerGlobalScope")}} インターフェイスと、その親の {{domxref("EventTarget")}} を継承しています。 @@ -21,33 +21,61 @@ l10n: ## インスタンスプロパティ +_このインターフェイスには {{domxref("WorkerGlobalScope")}} インターフェイス、およびその親である {{domxref("EventTarget")}} から継承したプロパティがあります。_ + - {{domxref("caches")}} {{ReadOnlyInline}} - : サービスワーカーに関連づけられた {{domxref("CacheStorage")}} オブジェクトを保持します。 - {{domxref("ServiceWorkerGlobalScope.clients")}} {{ReadOnlyInline}} - : サービスワーカーに関連付けられた {{domxref("Clients")}} オブジェクトを保持します。 +- {{domxref("ServiceWorkerGlobalScope.cookieStore")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : このサービスワーカーに関連付けられた {{domxref("CookieStore")}} オブジェクトを参照します。 - {{domxref("ServiceWorkerGlobalScope.registration")}} {{ReadOnlyInline}} - : サービスワーカーの登録を表す {{domxref("ServiceWorkerRegistration")}} オブジェクトを保持します。 +- {{domxref("ServiceWorkerGlobalScope.serviceWorker")}} {{ReadOnlyInline}} + - : サービスワーカーを表す {{domxref("ServiceWorker")}} オブジェクトを保持します。 + +## インスタンスメソッド + +_このインターフェイスには {{domxref("WorkerGlobalScope")}} インターフェイス、およびその親である {{domxref("EventTarget")}} から継承したメソッドがあります。_ + +- {{domxref("ServiceWorkerGlobalScope.skipWaiting()")}} + - : 現在のサービスワーカーの登録を、待ち状態からクライアントが使っている時のアクティブ状態に進めます。 ## イベント +このイベントを待ち受けするには、 {{domxref("EventTarget/addEventListener()", "addEventListener()")}} などのメソッドで使用するか、このインターフェイスの `onイベント名` プロパティにイベントリスナー設定するかしてください。 + - {{domxref("ServiceWorkerGlobalScope/activate_event", "activate")}} - : {{domxref("ServiceWorkerRegistration")}} が新しい {{domxref("ServiceWorkerRegistration.active")}} ワーカーを得た時に発生します。 -- {{domxref("ServiceWorkerGlobalScope.canmakepayment_event", "canmakepayment")}} {{Experimental_Inline}} - - : 決済アプリのサービスワーカーで発行され、決済を処理する準備ができたかどうかを調べるために使用されます。特に、販売者のウェブサイトが {{domxref("PaymentRequest.PaymentRequest", "new PaymentRequest()")}} を呼び出すと発行されます。 +- {{domxref("ServiceWorkerGlobalScope/backgroundfetchabort_event", "backgroundfetchabort")}} {{Experimental_Inline}} + - : ユーザーまたはアプリによって[バックグラウンドフェッチ](/ja/docs/Web/API/Background_Fetch_API)処理が中止された場合に発生します。 +- {{domxref("ServiceWorkerGlobalScope/backgroundfetchclick_event", "backgroundfetchclick")}} {{Experimental_Inline}} + - : ユーザーがUIをクリックして[バックグラウンドフェッチ](/ja/docs/Web/API/Background_Fetch_API)処理を実行したときに発生します。 +- {{domxref("ServiceWorkerGlobalScope/backgroundfetchfail_event", "backgroundfetchfail")}} {{Experimental_Inline}} + - : [バックグラウンドフェッチ](/ja/docs/Web/API/Background_Fetch_API)処理で、リクエストの少なくとも 1 つが失敗したときに発生します。 +- {{domxref("ServiceWorkerGlobalScope/backgroundfetchsuccess_event", "backgroundfetchsuccess")}} {{Experimental_Inline}} + - : [バックグラウンドフェッチ](/ja/docs/Web/API/Background_Fetch_API)処理で、リクエストされたすべてが成功したときに発生します。 +- {{domxref("ServiceWorkerGlobalScope/canmakepayment_event", "canmakepayment")}} {{Experimental_Inline}} + - : 決済アプリのサービスワーカーで発行され、決済を処理する準備ができたかどうかを調べるために使用されます。 + 特に、販売者のウェブサイトが {{domxref("PaymentRequest.PaymentRequest", "PaymentRequest()")}} コンストラクターを呼び出すと発生します。 - {{domxref("ServiceWorkerGlobalScope/contentdelete_event", "contentdelete")}} {{Experimental_Inline}} - - : {{domxref("ContentIndex", "コンテンツ索引", "", 1)}}からアイテムが取り除かれたときに発生します。 + - : {{domxref("ContentIndex")}} からアイテムが取り除かれたときに発生します。 +- {{domxref("ServiceWorkerGlobalScope/cookiechange_event", "cookiechange")}} {{Experimental_Inline}} + - : サービスワーカーの Cookie 変更購読リストと一致する Cookie 変更があった場合に発生します。 - {{domxref("ServiceWorkerGlobalScope/fetch_event", "fetch")}} - - : {{domxref("fetch()")}} が呼び出されたときに発生します。 + - : {{domxref("WorkerGlobalScope/fetch", "fetch()")}} が呼び出されたときに発生します。 - {{domxref("ServiceWorkerGlobalScope/install_event", "install")}} - : {{domxref("ServiceWorkerRegistration")}} が新しい {{domxref("ServiceWorkerRegistration.installing")}} ワーカーを得た時に発生します。 - {{domxref("ServiceWorkerGlobalScope/message_event", "message")}} - - : メッセージを受信したときに発生します。制御中のページは {{domxref("MessagePort.postMessage()")}} メソッドを使用してサービスワーカーにメッセージを送信することができます。サービスワーカーは任意で [`event.data.port`](https://html.spec.whatwg.org/multipage/comms.html#messageport) で公開されている {{domxref("MessagePort")}} を通じて、対応する制御中のページに返信することができます。 + - : メッセージを受信したときに発生します。制御中のページは {{domxref("MessagePort.postMessage()")}} メソッドを使用してサービスワーカーにメッセージを送信することができます。 +- {{domxref("ServiceWorkerGlobalScope/messageerror_event", "messageerror")}} + - : 受信メッセージがデシリアライズできなかった場合に発生します。 - {{domxref("ServiceWorkerGlobalScope/notificationclick_event", "notificationclick")}} - : 表示された通知をユーザーがクリックしたときに発生します。 - {{domxref("ServiceWorkerGlobalScope/notificationclose_event", "notificationclose")}} - : 表示された通知をユーザーが閉じたときに発生します。 -- {{domxref("ServiceWorkerGlobalScope.paymentrequest_event", "paymentrequest")}} {{Experimental_Inline}} - - : 販売者のウェブサイトで {{domxref("PaymentRequest.show()")}} メソッドを介して支払いフローが開始されたときに、支払いアプリで発行されます。 +- {{domxref("ServiceWorkerGlobalScope/paymentrequest_event", "paymentrequest")}} {{Experimental_Inline}} + - : 販売者のウェブサイトで {{domxref("PaymentRequest.show()")}} メソッドを介して支払いフローが開始されたときに、支払いアプリで発生します。 - {{domxref("ServiceWorkerGlobalScope/sync_event", "sync")}} - : サービスワーカーのクライアントページから {{domxref("SyncManager.register")}} への呼び出しが行われたときに発生します。ネットワークが有効であるか、すぐに利用可能になるのであれば、直ちに同期が試みられます。 - {{domxref("ServiceWorkerGlobalScope/periodicsync_event", "periodicsync")}} {{Experimental_Inline}} @@ -57,21 +85,11 @@ l10n: - {{domxref("ServiceWorkerGlobalScope/pushsubscriptionchange_event", "pushsubscriptionchange")}} - : プッシュ通知への加入が無効化されたとき、または無効化されようとするとき (例えば、プッシュ通知の有効期限が設定されたとき) に発生します。 -## インスタンスメソッド - -- {{domxref("ServiceWorkerGlobalScope.skipWaiting()")}} - - : 現在のサービスワーカーの登録を、待ち状態からクライアントが使っている時のアクティブ状態に進めます。 - -`ServiceWorkerGlobalScope` は {{domxref("WorkerGlobalScope")}} を実装しています。このため利用できる以下のプロパティもあります。 - -- {{domxref("fetch()")}} - - : リソース取得 (fetch) のプロセスを開始します。これはリクエストのレスポンスを表す {{domxref("Response")}} オブジェクトを解決するプロミスを返します。このアルゴリズムはサービスワーカーコンテキストに渡されるフェッチ処理のエントリーポイントです。 - ## 例 このコードスニペットは、[service worker prefetch の例](https://github.com/GoogleChrome/samples/blob/gh-pages/service-worker/prefetch/service-worker.js)([prefetch の例のライブ版](https://googlechrome.github.io/samples/service-worker/prefetch/)を参照してください)からのものです。 {{domxref("ServiceWorkerGlobalScope.fetch_event", "onfetch")}} イベントハンドラーは `fetch` イベントを監視します。イベントが発生した時、コードは {{domxref("Cache")}} オブジェクト内で、最初に一致したリクエストに対して解決するプロミスを返します。もし、何も一致しなかった場合は、コードはネットワークからレスポンスを読み取ります。 -さらに、このコードは {{domxref("fetch()")}} 操作で発生した例外を処理しています。 HTTP のエラーレスポンス(たとえば、404)は、例外を引き起こさないことに注意してください。適切なエラーコードセットを持った通常のレスポンスオブジェクトを返します。 +さらに、このコードは {{domxref("WorkerGlobalScope/fetch", "fetch()")}} 操作で発生した例外を処理しています。 HTTP のエラーレスポンス(たとえば、404)は、例外を引き起こさないことに注意してください。適切なエラーコードセットを持った通常のレスポンスオブジェクトを返します。 ```js self.addEventListener("fetch", (event) => { @@ -115,5 +133,3 @@ self.addEventListener("fetch", (event) => { - [サービスワーカーの使用](/ja/docs/Web/API/Service_Worker_API/Using_Service_Workers) - [サービスワーカーの基本的なコード例](https://github.com/mdn/dom-examples/tree/main/service-worker/simple-service-worker) -- [Is ServiceWorker ready?](https://jakearchibald.github.io/isserviceworkerready/) -- {{jsxref("Promise")}} From bec54a34db203fbea0a743271910c7752f8382d3 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Thu, 15 Aug 2024 17:58:15 +0900 Subject: [PATCH 23/28] =?UTF-8?q?2024/07/30=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deprecated_and_obsolete_features/index.md | 94 +++++++++++++------ 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.md b/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.md index 1db3a7a98aa0ec..1c3065f098bc88 100644 --- a/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.md +++ b/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.md @@ -2,20 +2,22 @@ title: 非推奨の機能、廃止された機能 slug: Web/JavaScript/Reference/Deprecated_and_obsolete_features l10n: - sourceCommit: b1171164863d3bb868de64ffc8ddec508599ed57 + sourceCommit: 758299969f63c13d235212f1adff79a649702adf --- -{{JsSidebar("More")}} +{{jsSidebar("More")}} このページのリストは JavaScript で廃止予定(まだ使用できるが削除する予定)とされた、あるいは既に廃止され使用不可となった機能の一覧です。 ## 非推奨の機能 -これらの非推奨機能はまだ使用可能かもしれません。しかし将来的には完全に削除されるでしょう。既にコード内でこれらを使用している場合は、代替となるコードに置き換えておく必要があります。 +これらの非推奨の機能は現在でも使用することができますが、すべての JavaScript エンジンで実装されているとは限らないため、注意して使用する必要があります。 コードからこれらの使用を除去するよう作業を行うべきです。 -これらの非推奨機能のいくつかは、 ECMAScript 仕様書の[付録 B](https://tc39.es/ecma262/#sec-additional-ecmascript-features-for-web-browsers) の章に掲載されています。この章は規範的なオプションとして記述されています。つまり、ウェブブラウザーのホストはこれらの機能を実装しなければなりませんが、ウェブ以外のホストは実装しなくても構いません。これらの機能を削除すると後方互換性の問題が発生し、旧形式のウェブサイトが壊れてしまうので、おそらく安定しているのでしょう。(JavaScript で「ウェブを壊すな」という設計目標があります。)それでも、これらはクロスプラットフォームで互換性がなく、すべての解析ツールで対応していないかもしれないので、付録 B の序文にあるように、使用しないことが推奨されます。 +これらの非推奨機能のいくつかは、 ECMAScript 仕様書の[付録 B](https://tc39.es/ecma262/multipage/additional-ecmascript-features-for-web-browsers.html) の章に掲載されています。この章は規範的なオプションとして記述されています。つまり、ウェブブラウザーのホストはこれらの機能を実装しなければなりませんが、ウェブ以外のホストは実装しなくても構いません。これらの機能を削除すると後方互換性の問題が発生し、旧形式のウェブサイトが壊れてしまうので、おそらく安定しているのでしょう。(JavaScript で「ウェブを壊すな」という設計目標があります。)それでも、これらはクロスプラットフォームで互換性がなく、すべての解析ツールで対応していないかもしれないので、付録 B の序文にあるように、使用しないことが推奨されます。 -> ... プログラマーは新しい ECMAScript コードを書くときに、これらの機能や振る舞いを使用したり、その存在を想定したりしてはいけません。... +> … この付録で指定された言語機能および動作にはすべて、1つまたは複数の望ましくない特性があり、古い使用方法がなくなれば、この仕様から除去されることになります。… +> +> …プログラマーは新しい ECMAScript コードを書くときに、これらの機能や振る舞いを使用したり、その存在を想定したりしてはいけません。… 他にも、仕様書本体にあるとはいえ、規範的なオプションとしてマークされているものもあり、依存してはいけません。 @@ -39,28 +41,37 @@ console.log("b"); 以下のプロパティは非推奨です。これらは[置換文字列](/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace)で使用しても効果がありません。 -| プロパティ | 説明 | -| ------------------------------------------------- | ---------------------------------------------------- | -| {{jsxref("RegExp/n", "$1-$9")}} | もしあれば、括弧で囲まれた部分文字列に一致します。 | -| {{jsxref("RegExp.input", "$_")}} | `input` を参照。 | -| {{jsxref("RegExp.lastMatch", "$&")}} | `lastMatch` を参照。 | -| {{jsxref("RegExp.lastParen", "$+")}} | `lastParen` を参照。 | -| {{jsxref("RegExp.leftContext", "$`")}} | `leftContext` を参照。 | -| {{jsxref("RegExp.rightContext", "$'")}} | `rightContext` を参照。 | -| {{jsxref("RegExp.input", "input")}} | 正規表現が一致する対象となる文字列。 | -| {{jsxref("RegExp.lastMatch", "lastMatch")}} | 最後に一致した文字。 | -| {{jsxref("RegExp.lastParen", "lastParen")}} | (もしあれば)最後に括弧で囲まれた部分文字列の一致。 | -| {{jsxref("RegExp.leftContext", "leftContext")}} | 一番最近の一致に先行する部分文字列。 | -| {{jsxref("RegExp.rightContext", "rightContext")}} | 一番最近の一致の後に続く部分文字列。 | +- [`$1–$9`](/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/n) + - : もしあれば、一致した括弧で囲まれた部分文字列です。 +- [`input`, `$_`](/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/input) + - : 正規表現を照合する文字列です。 +- [`lastMatch`, `$&`](/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastMatch) + - : 最後に一致した部分文字列です。 +- [`lastParen`, `$+`](/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastParen) + - : もしあれば、一致した括弧で囲まれた最後の部分文字列です。 +- [`leftContext`, `` $` ``](/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/leftContext) + - : 直近に一致した部分文字列の直前の部分文字列です。 +- [`rightContext`, `$'`](/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/rightContext) + - : 直近に一致した部分文字列の直後の部分文字列です。 > [!WARNING] > これらの静的プロパティは、[外部コードと対話する際の問題](https://github.com/tc39/proposal-regexp-legacy-features/blob/master/subclass-restriction-motivation.md#legacy-static-properties-regexp1-etc)を発生させる可能性があるため、使用しないようにしましょう。 {{jsxref("RegExp/compile", "compile()")}} メソッドは非推奨です。代わりに新しい `RegExp` のインスタンスを構築してください。 +以下の正規表現の構文は非推奨であり、[Unicode 非対応モード](/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode#unicode-aware_mode)でのみ利用できます。Unicode 対応モードでは、これらはすべて構文エラーとなります。 + +- [先読みアサーション](/ja/docs/Web/JavaScript/Reference/Regular_expressions/Lookahead_assertion)に[数量詞](/ja/docs/Web/JavaScript/Reference/Regular_expressions/Quantifier)をつけること。 +- 既存のキャプチャグループを参照しない[後方参照](/ja/docs/Web/JavaScript/Reference/Regular_expressions/Backreference)は、[古い 8 進数エスケープ](#エスケープシーケンス)となります。 +- [文字クラス](/ja/docs/Web/JavaScript/Reference/Regular_expressions/Character_class)において、一方の境界が文字クラスである文字の範囲を表す `-` 文字はリテラル文字になります。 +- 認識されないエスケープシーケンスは[「同一エスケープ」](/ja/docs/Web/JavaScript/Reference/Regular_expressions/Character_escape)として扱われます。 +- [文字クラス](/ja/docs/Web/JavaScript/Reference/Regular_expressions/Character_class)内で、`\cX` (`X` は数字または `_` )の形で形成されたエスケープシーケンスは、{{Glossary("ASCII")}} 文字の場合と同じ方法でデコードされます。`\c0` はモジュロ 32 を取ると `\cP` と同じです。加えて、`\cX` という形がどこかで検出され、`X` が認識された文字のいずれでもない場合、バックスラッシュはリテラル文字として扱われます。 +- `\k` シーケンスが[名前付きキャプチャグループ](/ja/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group)がない正規表現内に現れた場合、同一エスケープとして扱われます。 +- 構文文字である `]`、`{`、`}` が、文字クラスまたは量指定子の区切り文字の終わりとして解釈できない場合、エスケープせずに[そのまま](/ja/docs/Web/JavaScript/Reference/Regular_expressions/Literal_character)現れることがあります。 + ### Function -- 関数の {{jsxref("Global_Objects/Function/caller", "caller")}} プロパティと [`arguments.callee`](/ja/docs/Web/JavaScript/Reference/Functions/arguments/callee) プロパティは非推奨で、厳格モードでは使用できません。 +- 関数の {{jsxref("Function/caller", "caller")}} プロパティと [`arguments.callee`](/ja/docs/Web/JavaScript/Reference/Functions/arguments/callee) プロパティは非推奨で、厳格モードでは使用できません。 - 関数のプロパティとして `arguments` にアクセスする代わりに、関数クロージャの内部で {{jsxref("Functions/arguments", "arguments")}} オブジェクトを使用してください。 ### Object @@ -76,19 +87,42 @@ console.log("b"); ### Date -- {{jsxref("Global_Objects/Date/getYear", "getYear()")}} と {{jsxref("Global_Objects/Date/setYear", "setYear()")}} は「2000年問題」の影響を受けます。代替策として、{{jsxref("Global_Objects/Date/getFullYear", "getFullYear")}} および {{jsxref("Global_Objects/Date/setFullYear", "setFullYear")}} の使用が推奨されます。 -- {{jsxref("Global_Objects/Date/toGMTString", "toGMTString()")}} メソッドは非推奨です。代わりに {{jsxref("Global_Objects/Date/toUTCString", "toUTCString()")}} を使用してください。 +- {{jsxref("Date/getYear", "getYear()")}} と {{jsxref("Date/setYear", "setYear()")}} は「2000年問題」の影響を受けます。代替策として、{{jsxref("Date/getFullYear", "getFullYear")}} および {{jsxref("Date/setFullYear", "setFullYear")}} の使用が推奨されます。 +- `toGMTString()` メソッドは非推奨です。代わりに {{jsxref("Date/toUTCString", "toUTCString()")}} を使用してください。 ### エスケープシーケンス - 文字列内と正規表現リテラル内での、8 進表記のエスケープシーケンス (\ に続く、1 つ、2 つ、もしくは、3 つの 8 進表現の数字) は非推奨です。 -- {{jsxref("Global_Objects/escape", "escape")}} と {{jsxref("Global_Objects/unescape", "unescape")}} 関数は非推奨です。特殊文字のためのエスケープシーケンスをエンコードかデコードするためには、{{jsxref("Global_Objects/encodeURI", "encodeURI")}}、{{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}}、{{jsxref("Global_Objects/decodeURI", "decodeURI")}}、{{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent")}} を使用してください。 +- {{jsxref("escape()")}} と {{jsxref("unescape()")}} 関数は非推奨です。特殊文字のためのエスケープシーケンスをエンコードかデコードするためには、{{jsxref("encodeURI()")}}、{{jsxref("encodeURIComponent()")}}、{{jsxref("decodeURI()")}}、{{jsxref("decodeURIComponent()")}} を使用してください。 ### 文 [`with`](/ja/docs/Web/JavaScript/Reference/Statements/with) 文は非推奨であり、厳格モードでは利用できません。 -[`for...in`](/ja/docs/Web/JavaScript/Reference/Statements/for...in) ループヘッダーの `var` 宣言での初期化子は非推奨であり、厳格モードでは[構文エラー](/ja/docs/Web/JavaScript/Reference/Errors/Invalid_for-in_initializer)になります。厳格モードでない場合は、黙って無視されます。 +[`for...in`](/ja/docs/Web/JavaScript/Reference/Statements/for...in) ループヘッダーの `var` 宣言での初期化子は非推奨であり、厳格モードでは[構文エラー](/ja/docs/Web/JavaScript/Reference/Errors/Invalid_for-in_initializer)になります。初期化子の式が評価され、変数に割り当てられますが、ループの最初の反復処理で値がすぐに再割り当てされます。 + +通常、[`try...catch`](/ja/docs/Web/JavaScript/Reference/Statements/try...catch) 文の `catch` ブロックには、`catch()` でバインドされた変数と同じ名前の変数宣言を置くことはできません。拡張文法では、`catch` ブロックに `catch` でバインドされた識別子と同じ名前の宣言済み変数 [`var`](/ja/docs/Web/JavaScript/Reference/Statements/var) を置くことができます。ただし、`catch` のバインドが単純な識別子であり、[分割代入](/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) ではない場合に限ります。ただし、この変数の初期化と割り当ては、上位のスコープ変数ではなく、`catch` にバインドされた識別子に対してのみ作用します。このため、動作がわかりにくい場合があります。 + +```js +var a = 2; +try { + throw 42; +} catch (a) { + var a = 1; // この 1 は、外側の `a` ではなく、捕捉された `a` に代入される +} +console.log(a); // 2 + +try { + throw 42; + // メモ: 内部で宣言されている `a` との重複を避けるため、 + // `err` に変更してみる +} catch (err) { + var a = 1; // この 1 は、上位スコープの `a` に代入される +} +console.log(a); // 1 +``` + +これは仕様の付録Bに掲載されているため、どこでも実装されているとは限りません。 `catch` ブロックで宣言された変数と、`catch` バインドされた識別子との間で名前の競合が生じないようにしてください。 ## 廃止された機能 @@ -139,7 +173,7 @@ console.log("b"); ### Date -- `Date.prototype.toLocaleFormat()` は廃止されました。代わりに [`toLocaleString`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) または [`Intl.DateTimeFormat`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat) を使用してください。 +- C 言語の `strftime()` 関数で期待されるのと同じ形式の書式文字列を使用する `Date.prototype.toLocaleFormat()` は廃止されました。代わりに [`toLocaleString()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) または [`Intl.DateTimeFormat`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat) を使用してください。 ### Array @@ -158,10 +192,10 @@ console.log("b"); - `Proxy.create` および `Proxy.createFunction` は非推奨です。代わりに {{jsxref("Proxy/Proxy", "Proxy()")}} コンストラクターを使用してください。 - 以下のトラップは廃止されました。 - - `hasOwn` ([バグ 980565](https://bugzilla.mozilla.org/show_bug.cgi?id=980565), Firefox 33) - - `getEnumerablePropertyKeys` ([バグ 783829](https://bugzilla.mozilla.org/show_bug.cgi?id=783829), Firefox 37) - - `getOwnPropertyNames` ([バグ 1007334](https://bugzilla.mozilla.org/show_bug.cgi?id=1007334), Firefox 33) - - `keys` ([バグ 1007334](https://bugzilla.mozilla.org/show_bug.cgi?id=1007334), Firefox 33) + - `hasOwn` ([バグ 980565](https://bugzil.la/980565), Firefox 33) + - `getEnumerablePropertyKeys` ([バグ 783829](https://bugzil.la/783829), Firefox 37) + - `getOwnPropertyNames` ([バグ 1007334](https://bugzil.la/1007334), Firefox 33) + - `keys` ([バグ 1007334](https://bugzil.la/1007334), Firefox 33) ### ParallelArray @@ -171,7 +205,7 @@ console.log("b"); - `for each...in` は廃止されました。代わりに {{jsxref("Statements/for...of", "for...of")}} を使用してください。 - let ブロックと let 式は廃止されました。 -- [式クロージャ](/ja/docs/Web/JavaScript/Reference/Errors/Deprecated_expression_closures)は廃止されました。代わりに通常の{{jsxref("Operators/function", "関数", "", 1)}}または{{jsxref("Functions/Arrow_functions", "アロー関数", "", 1)}}を使用してください。 +- 式クロージャ(`function () 1` を `function () { return 1; }` の短縮形として使うこと)は廃止されました。代わりに通常の{{jsxref("Operators/function", "関数", "", 1)}}または{{jsxref("Functions/Arrow_functions", "アロー関数", "", 1)}}を使用してください。 ### ソーステキストの取得 @@ -183,7 +217,7 @@ console.log("b"); 配列内包とジェネレーター内包が削除されました。 -``` +```js-nolint // 古い配列内包 [for (x of iterable) x] [for (x of iterable) if (condition) x] From 1c695f076f3ee1427b59f1e0f759398db2e920fa Mon Sep 17 00:00:00 2001 From: mdn-bot <108879845+mdn-bot@users.noreply.github.com> Date: Mon, 19 Aug 2024 01:30:00 +0000 Subject: [PATCH 24/28] ja: sync translated content --- files/ja/_redirects.txt | 18 +++++------ files/ja/_wikihistory.json | 30 +++++++++---------- .../api/console/countreset_static/index.md | 2 +- .../console/groupcollapsed_static/index.md | 2 +- .../web/api/console/groupend_static/index.md | 2 +- .../api/console/profileend_static/index.md | 2 +- .../web/api/console/timeend_static/index.md | 2 +- .../web/api/console/timelog_static/index.md | 2 +- .../web/api/console/timestamp_static/index.md | 2 +- .../web/api/cssimportrule/stylesheet/index.md | 3 +- .../api/csspropertyrule/initialvalue/index.md | 3 +- .../idbtransaction/objectstorenames/index.md | 2 +- files/ja/web/api/usbdevice/productid/index.md | 2 +- files/ja/web/api/usbdevice/vendorid/index.md | 2 +- 14 files changed, 36 insertions(+), 38 deletions(-) diff --git a/files/ja/_redirects.txt b/files/ja/_redirects.txt index ec72dd7269a10a..7ebb1cd0827a97 100644 --- a/files/ja/_redirects.txt +++ b/files/ja/_redirects.txt @@ -700,7 +700,7 @@ /ja/docs/DOM/console.dir /ja/docs/Web/API/console/dir_static /ja/docs/DOM/console.log /ja/docs/Web/API/console/log_static /ja/docs/DOM/console.time /ja/docs/Web/API/console/time_static -/ja/docs/DOM/console.timeEnd /ja/docs/Web/API/console/timeend_static +/ja/docs/DOM/console.timeEnd /ja/docs/Web/API/console/timeEnd_static /ja/docs/DOM/dispatchEvent_example /ja/docs/Web/Events/Creating_and_triggering_events /ja/docs/DOM/document /ja/docs/Web/API/Document /ja/docs/DOM/document.URL /ja/docs/Web/API/Document/URL @@ -2657,7 +2657,7 @@ /ja/docs/Web/API/Console/error /ja/docs/Web/API/console/error_static /ja/docs/Web/API/Console/log /ja/docs/Web/API/console/log_static /ja/docs/Web/API/Console/time /ja/docs/Web/API/console/time_static -/ja/docs/Web/API/Console/timeEnd /ja/docs/Web/API/console/timeend_static +/ja/docs/Web/API/Console/timeEnd /ja/docs/Web/API/console/timeEnd_static /ja/docs/Web/API/Constraint_validation /ja/docs/Learn/Forms/Form_validation /ja/docs/Web/API/Coordinates /ja/docs/Web/API/GeolocationCoordinates /ja/docs/Web/API/DOMPoint/fromPoint /ja/docs/Web/API/DOMPoint/fromPoint_static @@ -3257,22 +3257,22 @@ /ja/docs/Web/API/console.dir /ja/docs/Web/API/console/dir_static /ja/docs/Web/API/console.log /ja/docs/Web/API/console/log_static /ja/docs/Web/API/console.time /ja/docs/Web/API/console/time_static -/ja/docs/Web/API/console.timeEnd /ja/docs/Web/API/console/timeend_static +/ja/docs/Web/API/console.timeEnd /ja/docs/Web/API/console/timeEnd_static /ja/docs/Web/API/console/assert /ja/docs/Web/API/console/assert_static /ja/docs/Web/API/console/clear /ja/docs/Web/API/console/clear_static /ja/docs/Web/API/console/count /ja/docs/Web/API/console/count_static -/ja/docs/Web/API/console/countReset /ja/docs/Web/API/console/countreset_static +/ja/docs/Web/API/console/countReset /ja/docs/Web/API/console/countReset_static /ja/docs/Web/API/console/debug /ja/docs/Web/API/console/debug_static /ja/docs/Web/API/console/dirxml /ja/docs/Web/API/console/dirxml_static /ja/docs/Web/API/console/group /ja/docs/Web/API/console/group_static -/ja/docs/Web/API/console/groupCollapsed /ja/docs/Web/API/console/groupcollapsed_static -/ja/docs/Web/API/console/groupEnd /ja/docs/Web/API/console/groupend_static +/ja/docs/Web/API/console/groupCollapsed /ja/docs/Web/API/console/groupCollapsed_static +/ja/docs/Web/API/console/groupEnd /ja/docs/Web/API/console/groupEnd_static /ja/docs/Web/API/console/info /ja/docs/Web/API/console/info_static /ja/docs/Web/API/console/profile /ja/docs/Web/API/console/profile_static -/ja/docs/Web/API/console/profileEnd /ja/docs/Web/API/console/profileend_static +/ja/docs/Web/API/console/profileEnd /ja/docs/Web/API/console/profileEnd_static /ja/docs/Web/API/console/table /ja/docs/Web/API/console/table_static -/ja/docs/Web/API/console/timeLog /ja/docs/Web/API/console/timelog_static -/ja/docs/Web/API/console/timeStamp /ja/docs/Web/API/console/timestamp_static +/ja/docs/Web/API/console/timeLog /ja/docs/Web/API/console/timeLog_static +/ja/docs/Web/API/console/timeStamp /ja/docs/Web/API/console/timeStamp_static /ja/docs/Web/API/console/trace /ja/docs/Web/API/console/trace_static /ja/docs/Web/API/console/warn /ja/docs/Web/API/console/warn_static /ja/docs/Web/API/crypto_property /ja/docs/Web/API/Window/crypto diff --git a/files/ja/_wikihistory.json b/files/ja/_wikihistory.json index e0c5f379618327..8d7cd239a4f451 100644 --- a/files/ja/_wikihistory.json +++ b/files/ja/_wikihistory.json @@ -15115,14 +15115,14 @@ "modified": "2020-11-27T13:49:44.683Z", "contributors": ["yumetodo", "853419196", "yyss"] }, + "Web/API/console/countReset_static": { + "modified": "2020-11-27T14:37:31.289Z", + "contributors": ["yumetodo"] + }, "Web/API/console/count_static": { "modified": "2020-11-27T14:24:35.469Z", "contributors": ["yumetodo", "yyss"] }, - "Web/API/console/countreset_static": { - "modified": "2020-11-27T14:37:31.289Z", - "contributors": ["yumetodo"] - }, "Web/API/console/debug_static": { "modified": "2020-11-27T14:40:02.073Z", "contributors": ["yumetodo", "silverskyvicto"] @@ -15131,35 +15131,35 @@ "modified": "2019-03-23T22:34:53.031Z", "contributors": ["yyss"] }, - "Web/API/console/group_static": { - "modified": "2020-10-15T21:45:35.788Z", - "contributors": ["munieru_jp", "dskmori", "yyss"] - }, - "Web/API/console/groupcollapsed_static": { + "Web/API/console/groupCollapsed_static": { "modified": "2019-03-23T22:34:55.714Z", "contributors": ["yyss"] }, - "Web/API/console/groupend_static": { + "Web/API/console/groupEnd_static": { "modified": "2019-03-23T22:34:56.119Z", "contributors": ["yyss"] }, + "Web/API/console/group_static": { + "modified": "2020-10-15T21:45:35.788Z", + "contributors": ["munieru_jp", "dskmori", "yyss"] + }, "Web/API/console/info_static": { "modified": "2020-10-15T21:45:37.023Z", "contributors": ["u_7cc", "yyss"] }, - "Web/API/console/profile_static": { - "modified": "2019-03-23T22:34:55.973Z", + "Web/API/console/profileEnd_static": { + "modified": "2019-03-23T22:34:42.618Z", "contributors": ["yyss"] }, - "Web/API/console/profileend_static": { - "modified": "2019-03-23T22:34:42.618Z", + "Web/API/console/profile_static": { + "modified": "2019-03-23T22:34:55.973Z", "contributors": ["yyss"] }, "Web/API/console/table_static": { "modified": "2019-03-23T22:34:44.337Z", "contributors": ["yyss"] }, - "Web/API/console/timestamp_static": { + "Web/API/console/timeStamp_static": { "modified": "2019-03-23T22:34:51.368Z", "contributors": ["yyss"] }, diff --git a/files/ja/web/api/console/countreset_static/index.md b/files/ja/web/api/console/countreset_static/index.md index 783722b2624f31..a9032a34623e26 100644 --- a/files/ja/web/api/console/countreset_static/index.md +++ b/files/ja/web/api/console/countreset_static/index.md @@ -1,6 +1,6 @@ --- title: console.countReset() -slug: Web/API/console/countreset_static +slug: Web/API/console/countReset_static --- {{APIRef("Console API")}} diff --git a/files/ja/web/api/console/groupcollapsed_static/index.md b/files/ja/web/api/console/groupcollapsed_static/index.md index 2bc6be887d6c49..2359bf5f3546ad 100644 --- a/files/ja/web/api/console/groupcollapsed_static/index.md +++ b/files/ja/web/api/console/groupcollapsed_static/index.md @@ -1,6 +1,6 @@ --- title: console.groupCollapsed() -slug: Web/API/console/groupcollapsed_static +slug: Web/API/console/groupCollapsed_static --- {{APIRef("Console API")}} diff --git a/files/ja/web/api/console/groupend_static/index.md b/files/ja/web/api/console/groupend_static/index.md index 8030c218debbf7..d03e8f9902e061 100644 --- a/files/ja/web/api/console/groupend_static/index.md +++ b/files/ja/web/api/console/groupend_static/index.md @@ -1,6 +1,6 @@ --- title: console.groupEnd() -slug: Web/API/console/groupend_static +slug: Web/API/console/groupEnd_static --- {{APIRef("Console API")}} diff --git a/files/ja/web/api/console/profileend_static/index.md b/files/ja/web/api/console/profileend_static/index.md index 2382be02c84599..5e131633124914 100644 --- a/files/ja/web/api/console/profileend_static/index.md +++ b/files/ja/web/api/console/profileend_static/index.md @@ -1,6 +1,6 @@ --- title: console.profileEnd() -slug: Web/API/console/profileend_static +slug: Web/API/console/profileEnd_static --- {{APIRef("Console API")}}{{Non-standard_header}} diff --git a/files/ja/web/api/console/timeend_static/index.md b/files/ja/web/api/console/timeend_static/index.md index 535e0a82e0865b..fe92b0446ccf48 100644 --- a/files/ja/web/api/console/timeend_static/index.md +++ b/files/ja/web/api/console/timeend_static/index.md @@ -1,6 +1,6 @@ --- title: console.timeEnd() -slug: Web/API/console/timeend_static +slug: Web/API/console/timeEnd_static --- {{APIRef("Console API")}} diff --git a/files/ja/web/api/console/timelog_static/index.md b/files/ja/web/api/console/timelog_static/index.md index 0285799f2aae0f..3238d4c632da3f 100644 --- a/files/ja/web/api/console/timelog_static/index.md +++ b/files/ja/web/api/console/timelog_static/index.md @@ -1,6 +1,6 @@ --- title: console.timeLog() -slug: Web/API/console/timelog_static +slug: Web/API/console/timeLog_static --- {{APIRef("Console API")}} diff --git a/files/ja/web/api/console/timestamp_static/index.md b/files/ja/web/api/console/timestamp_static/index.md index 98acf3ba697d0e..f70761ae29a13e 100644 --- a/files/ja/web/api/console/timestamp_static/index.md +++ b/files/ja/web/api/console/timestamp_static/index.md @@ -1,6 +1,6 @@ --- title: console.timeStamp() -slug: Web/API/console/timestamp_static +slug: Web/API/console/timeStamp_static --- {{APIRef("Console API")}}{{Non-standard_header}} diff --git a/files/ja/web/api/cssimportrule/stylesheet/index.md b/files/ja/web/api/cssimportrule/stylesheet/index.md index f17bfd85a553d3..1ce28b43d14731 100644 --- a/files/ja/web/api/cssimportrule/stylesheet/index.md +++ b/files/ja/web/api/cssimportrule/stylesheet/index.md @@ -1,7 +1,6 @@ --- title: "CSSImportRule: stylesheet プロパティ" -short-title: stylesheet -slug: Web/API/CSSImportRule/stylesheet +slug: Web/API/CSSImportRule/styleSheet l10n: sourceCommit: d76defab4ca13261e9de81ae1df125345f847b0a --- diff --git a/files/ja/web/api/csspropertyrule/initialvalue/index.md b/files/ja/web/api/csspropertyrule/initialvalue/index.md index ad8e96fe461997..3260bca89ddc8f 100644 --- a/files/ja/web/api/csspropertyrule/initialvalue/index.md +++ b/files/ja/web/api/csspropertyrule/initialvalue/index.md @@ -1,7 +1,6 @@ --- title: "CSSPropertyRule: initialValue プロパティ" -short-title: initialValue -slug: Web/API/CSSPropertyRule/initialvalue +slug: Web/API/CSSPropertyRule/initialValue l10n: sourceCommit: d76defab4ca13261e9de81ae1df125345f847b0a --- diff --git a/files/ja/web/api/idbtransaction/objectstorenames/index.md b/files/ja/web/api/idbtransaction/objectstorenames/index.md index ea76f30ed75433..778bd781ba9e38 100644 --- a/files/ja/web/api/idbtransaction/objectstorenames/index.md +++ b/files/ja/web/api/idbtransaction/objectstorenames/index.md @@ -1,6 +1,6 @@ --- title: "IDBTransaction: objectStoreNames プロパティ" -slug: Web/API/IDBTransaction/ObjectStoreNames +slug: Web/API/IDBTransaction/objectStoreNames l10n: sourceCommit: eab4066e72d5478de920e4020e5db71214dcffa6 --- diff --git a/files/ja/web/api/usbdevice/productid/index.md b/files/ja/web/api/usbdevice/productid/index.md index bfb40e95b82a6e..7267a665547557 100644 --- a/files/ja/web/api/usbdevice/productid/index.md +++ b/files/ja/web/api/usbdevice/productid/index.md @@ -1,6 +1,6 @@ --- title: "USBDevice: productId プロパティ" -slug: Web/API/USBDevice/productID +slug: Web/API/USBDevice/productId l10n: sourceCommit: 0c8a320b035cf625c1df67713a94ead2e7f3aec6 --- diff --git a/files/ja/web/api/usbdevice/vendorid/index.md b/files/ja/web/api/usbdevice/vendorid/index.md index e09e6560eeb9a7..982f84e4c760dc 100644 --- a/files/ja/web/api/usbdevice/vendorid/index.md +++ b/files/ja/web/api/usbdevice/vendorid/index.md @@ -1,6 +1,6 @@ --- title: "USBDevice: vendorId プロパティ" -slug: Web/API/USBDevice/vendorID +slug: Web/API/USBDevice/vendorId l10n: sourceCommit: 0c8a320b035cf625c1df67713a94ead2e7f3aec6 --- From 87869c1cb702c15345dbcbd8a7dfd4ac89ef5389 Mon Sep 17 00:00:00 2001 From: MDN Web Docs GitHub Bot <108879845+mdn-bot@users.noreply.github.com> Date: Mon, 19 Aug 2024 17:36:18 +0200 Subject: [PATCH 25/28] [es] sync translated content (#23144) es: sync translated content --- files/es/_redirects.txt | 2 +- files/es/_wikihistory.json | 8 ++++---- files/es/web/api/console/timeend_static/index.md | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/files/es/_redirects.txt b/files/es/_redirects.txt index 437cf9dce1b2e7..aeb3d8d7780cdc 100644 --- a/files/es/_redirects.txt +++ b/files/es/_redirects.txt @@ -1763,7 +1763,7 @@ /es/docs/Web/API/console/log /es/docs/Web/API/console/log_static /es/docs/Web/API/console/table /es/docs/Web/API/console/table_static /es/docs/Web/API/console/time /es/docs/Web/API/console/time_static -/es/docs/Web/API/console/timeEnd /es/docs/Web/API/console/timeend_static +/es/docs/Web/API/console/timeEnd /es/docs/Web/API/console/timeEnd_static /es/docs/Web/API/console/trace /es/docs/Web/API/console/trace_static /es/docs/Web/API/console/warn /es/docs/Web/API/console/warn_static /es/docs/Web/API/crypto_property /es/docs/Web/API/Window/crypto diff --git a/files/es/_wikihistory.json b/files/es/_wikihistory.json index 579c9131e47322..68fbf350010711 100644 --- a/files/es/_wikihistory.json +++ b/files/es/_wikihistory.json @@ -5755,14 +5755,14 @@ "modified": "2019-03-23T22:20:30.589Z", "contributors": ["AlePerez92"] }, + "Web/API/console/timeEnd_static": { + "modified": "2020-10-15T22:13:11.825Z", + "contributors": ["xlhector10"] + }, "Web/API/console/time_static": { "modified": "2019-03-18T21:42:22.745Z", "contributors": ["jotaoncode"] }, - "Web/API/console/timeend_static": { - "modified": "2020-10-15T22:13:11.825Z", - "contributors": ["xlhector10"] - }, "Web/API/console/trace_static": { "modified": "2019-03-23T22:22:51.545Z", "contributors": ["Axl-Nolasco"] diff --git a/files/es/web/api/console/timeend_static/index.md b/files/es/web/api/console/timeend_static/index.md index bc84372a79a0f8..48a9be3667dcbc 100644 --- a/files/es/web/api/console/timeend_static/index.md +++ b/files/es/web/api/console/timeend_static/index.md @@ -1,6 +1,6 @@ --- title: Console.timeEnd() -slug: Web/API/console/timeend_static +slug: Web/API/console/timeEnd_static --- {{APIRef("Console API")}} From e321d9d5d6d410e62926f26f665286135ed07b82 Mon Sep 17 00:00:00 2001 From: Chunhui Fu Date: Tue, 20 Aug 2024 09:04:41 +0800 Subject: [PATCH 26/28] [zh-cn]: update valid datetime values list (#23153) Co-authored-by: Jason Ren <40999116+jasonren0403@users.noreply.github.com> --- files/zh-cn/web/html/element/time/index.md | 164 +++++++++++++++------ 1 file changed, 123 insertions(+), 41 deletions(-) diff --git a/files/zh-cn/web/html/element/time/index.md b/files/zh-cn/web/html/element/time/index.md index 626a497dc966c1..cf0207da8f648b 100644 --- a/files/zh-cn/web/html/element/time/index.md +++ b/files/zh-cn/web/html/element/time/index.md @@ -2,7 +2,7 @@ title: