Building up a basic demo with Three.js - 游戏开发

Building up a basic demo with Three.js
======================================

游戏中一个典型的 3D 场景 (最简单的那种) 包含标准的物品比如在坐标轴中的形状，一个实际可看到他们的摄像机，灯光和材质让其看起来不错，动画使其生动等等。 **Three.js**, 和其他 3D 库一样，提供内置的 helper 函数来帮助你尽可能快地实现通用的 3D 功能 . 在这篇文章我们会带你了解使用 Three 的基本知识，包含设置开发者环境，必要的 HTML 结构，Three.js 对象基础，以及如何创建一个基本的 demo.

**备注：** 我们选择 Three.js 因为它是最流行的WebGL 库之一，并且很容易上手。我们不会介绍任何其他更好的 WebGL 库，你可以自由选择其他库做尝试，比如 CopperLicht, GLGE, OSG.js, O3D, 或者其他你喜欢的库。

环境设置
----

开始用 Three.js, 你不需要准备太多，只需：

* 确保使用的支持 WebGL 的现代浏览器，例如最新版的 Firefox 或 Chrome.
* 创建一个目录保存例子。
* 复制最新的压缩版 Three.js 到你的目录。
* 用单独的浏览器 tab 打开 Three.js 文档 — 对应参考很有用。
HTML 结构
-------

这是将用到的 HTML 结构。

```html
<!doctype html>
<html>
  <head>
    meta charset="utf-8">
    <title>MDN Games: Three.js demo</title>
    <style>
 body {
 margin: 0;
 padding: 0;
 }
 canvas {
 width: 100%;
 height: 100%;
 }
 </style>
  </head>
  <body>
    <script src="three.min.js"></script>
    <script>
 var WIDTH = window.innerWidth;
 var HEIGHT = window.innerHeight;
 /\* all our JavaScript code goes here \*/
 </script>
  </body>
</html>
```

It contains some basic information like the document `<title>`, and some CSS to set the `width` and `height` of the `<canvas>` element that Three.js will insert on the page to 100% so that it will fill the entire available viewport space. The first `<script>` element includes the Three.js library in the page, and we will write our example code into the second one. There are two helper variables already included, which store the window's `width` and `height`.

Before reading on, copy this code to a new text file, and save it in your working directory as `index.html`.

渲染器
---

A renderer is a tool that displays scenes right in your browser. There are a few different renderers: WebGL is the default one, and the others you can use are Canvas, SVG, CSS and DOM. They differ in a way everything is rendered, so the WebGL implementation will work differently than the CSS one, but the idea is to have it look exactly the same for the end user. Thanks to this approach, a fallback can be used if the primary technology is not supported by the browser.

```js
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0xdddddd, 1);
document.body.appendChild(renderer.domElement);
```

We are creating a new WebGL renderer, setting it's size to fit the whole available space on the screen and appending the DOM structure to the page. You probably noticed the `antialias` parameter in the first line — this enables the edges of the shapes to be rendered a little more smoothly. The `setClearColor()` method sets our background to a light gray colour instead of the default black one.

Add this code into the second `<script>` element, just below the JavaScript comment.

场景
--

A scene is the place where everything happens. When creating new objects in the demo, we will be adding them all to the scene to make them visible on the screen. In three.js, the scene is reperesented by a `Scene` object. Let's create it, by adding the following line below our previous lines:

```js
var scene = new THREE.Scene();
```

Later on we will be using the `.add()` method to add objects to the scene.

摄像机
---

我们有渲染场景，但是我们仍然需要一个摄像机来观察场景 - 想象没有摄像机的电影场景。下面的代码将摄像机放在三维坐标系中，并将其指向我们的场景，这样人们就能看到一些东西：

```js
var camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT);
camera.position.z = 50;
scene.add(camera);
```

Add these lines to your code, below the prevous ones.

There are other types of camera available (Cube, Orthographic), but the simplest is the Perspective one. To initialize it we have to set its field of view and aspect ratio — the first one is used to set how much is seen, and a proper aspect ratio is important for the objects on the screen to have the right proportions when rendered and not look stretched. Let's explain the values we are setting in the code above:

* The value we set for the field of view, 70, is something we can experiment with — the higher the value, the greater the amount of scene the camera will show. Imagine a normal camera view, versus a fish eye effect, which allows a lot more to be seen. The default value is 50.
* The aspect ratio is set to the current width and height of the window so it will be dynamically adjusted. We could set a fixed ratio — for example 16 ⁄ 9, which is the aspect ratio of a widescreen TV. The default value is 1.
* The `z` position with the value of 50 units is the distance between the camera and the center of the scene on the `z` axis — here we're moving the camera back so the objects on the scene can be viewed. 50 feels ok as it's not too near and not too far and the sizes of the objects allow them to stay on the scene within the given field of view. The `x` and `y` values, if not specified, will default to 0.

You should experiment with these values and see how they change what you see in the scene.

**备注：** The distance values (e.g. for the camera z position) are unitless, and can basically be anything you deem suitable for your scene — milimeters, meters, feet, or miles — it's up to you.

Rendering the scene
-------------------

Everything is ready, but we still can't see anything. Although we set the renderer up, we still have to actually render everything. Our `render()` function will do this job, with a little help from `requestAnimationFrame()`, which causes the scene to be re-rendered constantly on every frame:

```js
function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
render();
```

On every new frame the `render` function is invoked and the `renderer` renders the `scene` and the `camera`. Right after the function declaration we're invoking it for the first time to start the loop, after which it will be used indefinitely.

Again add the new code below your previous additions, then try saving the file and loading it in your browser. You should now see a gray window. Congratulations!

Geometry
--------

Now the scene is properly rendering we can start adding 3D shapes to it. To speed up development Three.js provides a bunch of predefined primitives that you can to create shapes instantly in a single line of code. There's cubes, spheres, cylinders and more complicated shapes available. Drawing the needed vertices and faces for given shape is taken care of by the framework, so we can focus on the high level coding. Let's start by defining the geometry for a cube shape — add the following just above the `render()` function:

```js
var boxGeometry = new THREE.BoxGeometry(10, 10, 10);
```

In this case we define a simple cube that is 10 x 10 x 10 units. The geometry itself is not enough though — we also need a material that will be used for our shape.

Material
--------

Material is that thing covering the object — the colors or texture on its surface. In our case we will use a simple blue color to paint our box. There are predefined materials that can be used: Basic, Phong, Lambert. We will play with the last two later on, but for now the Basic one should be enough:

```js
var basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095dd });
```

Add this line below the previous one.

Our material is ready, but what to do next?

Mesh
----

To apply the material to a geometry a mesh is used. It takes a shape and adds the specified material to every face:

```js
var cube = new THREE.Mesh(boxGeometry, basicMaterial);
```

Again, add this line below the previous one.

Adding the cube to the scene
----------------------------

We've now created the actual cube using the geometry and material defined earlier. The last thing to do is to actually add the cube to our scene — add this line below the previous one:

```js
scene.add(cube);
```

If you save and refresh now, your object will look like a square, because it's facing the camera. The good thing about objects is that we can move them on the scene however we want, for example rotating and scaling as we like. Let's apply a little bit of rotation to the cube, so we can see more than one face — again, add below the previous one:

```js
cube.rotation.set(0.4, 0.2, 0);
```

Congratulations, you've created your first object in a 3D environment! It was easier than you thought, right? Here's how it should look:

![Blue cube on a gray background rendered with Three.js.](/zh-CN/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js/cube.png)

And here's the code we have created so far:

You can also check it out on GitHub.

More shapes and materials
-------------------------

Now we will add more shapes to the scene and explore other shapes, materials, lighting, and more. Let's move the cube to the left to make space for some friends — add the following line just below the previous one:

```js
cube.position.x = -25;
```

Now onto the shapes and materials: what would you say for a torus using the Phong material? Try adding the following lines just below the lines that define the cube.

```js
var torusGeometry = new THREE.TorusGeometry(7, 1, 6, 12);
var phongMaterial = new THREE.MeshPhongMaterial({ color: 0xff9500 });
var torus = new THREE.Mesh(torusGeometry, phongMaterial);
scene.add(torus);
```

Thee lines will add a torus geometry; the `TorusGeometry()` method's parameters define and the parameters are `radius`, `tube diameter`, `radial segment count` and `tubular segment count`. The Phong material should look more glossy than the simple color of the box that was using the Basic material, although at the moment it will just look black.

We can have even crazier predefined shapes; let's play some more — add the following lines below the ones that defined the torus:

```js
var dodecahedronGeometry = new THREE.DodecahedronGeometry(7);
var lambertMaterial = new THREE.MeshLambertMaterial({ color: 0xeaeff2 });
var dodecahedron = new THREE.Mesh(dodecahedronGeometry, lambertMaterial);
dodecahedron.position.x = 25;
scene.add(dodecahedron);
```

This time we are creating a dodecahedron, which is a shape containing twelve flat faces. The parameter `DodecahedronGeometry()` takes is the size of the object. We're using a Lambert material here, which is similar to Phong, but should be less glossy (again, black for now.) We're moving the object to the right, so it's not in the same place as the box or torus.

As mentioned above, the new objects currently just look black. To have both the Phong and Lambert materials properly visible we need a source of light.

Lights
------

There are various types of light sources available in Three.js; the most basic one is the `PointLight`, which works like a flashlight — shinig a spotlight in a given direction. Add the following below your shapre definitions:

```js
var light = new THREE.PointLight(0xffffff);
light.position.set(-10, 15, 50);
scene.add(light);
```

We define a white point of light, set it's position a bit away from the center of the scene so it can light up some parts of the shapes, and add it to the scene. Now everything works as it should — all three shapes are visible. You should check the documentation for other types of light like Ambient, Directional, Hemisphere or Spot, and experiment with placing them on the scene to see the effects.

![Shapes: blue cube, dark yellow torus and dark gray dodecahedron on a gray background rendered with Three.js.](/zh-CN/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js/shapes.png)

This looks a little bit boring though. In a game something is usually happening — we can see animations and such — so let's try to breathe a little life into those shapes by animating them.

Animation
---------

We already used rotation to adjust the position of the cube; we could also scale the shapes, or change thier positions. To show actual animation, we need to make changes to these values inside the render loop so, they are updated on every frame.

### Rotation

Rotating is quite easy — all you need to do is to add a defined value to the given direction of the rotation on each frame. Add this line of code right after the `requestAnimationFrame()` invocation in the `render` function:

```js
cube.rotation.y += 0.01;
```

It will rotate the cube on every frame by a tiny bit, so it will look like a smooth animation.

### Scaling

We can also scale a given object. By applying a constant value we could make it grow or shrink once, but let's make it more interesting. First, we will need a helper variable called `t` for counting the elapsed time. Add it right before the `render()` function:

```js
var t = 0;
```

Now let's increase the value by a given constant value on each frame of the animation; add the following lines just below the `requestAnimationFrame()` invocation:

```js
t += 0.01;
torus.scale.y = Math.abs(Math.sin(t));
```

This way we'll be able to use `Math.sin` and end up with quite an interesting result: this will scale the torus and repeat the whole process, as `sin` is a periodic function. We're wrapping the scale value in `Math.abs` to pass the absolute values (greater or equal to 0), because sin is between -1 and 0, and for negative values the torus might render unexpectedly (in this case it looks black half the time.)

Now onto the movement part.

### Moving

Beside rotation and scaling we can also move objects around the scene. Add the following, again just below the `requestAnimationFrame()` invocation:

```js
dodecahedron.position.y = -7 \* Math.sin(t \* 2);
```

This will move the dodecahedron up and down by applying the `sin()` value to the y axis on each frame, with a little bit of adjustment to make it look cooler. Try changing the values to see how it affects the animations.

Conclusion
----------

Here's the final piece of the code:

You can also see it on GitHub and fork the repository if you want to play with it yourself locally. Now you know the basics of Three.js, you can get back to the parent page about 3D on the Web.

You should also try learning raw WebGL, so you can get a better understanding of what's going on. See our WebGL documentation.


移动端触摸控制 - 游戏开发

移动端触摸控制
=======

* Overview: Control mechanisms
* 下一页  (en-US)

未来手游一定是 Web 的天下，许多开发在游戏开发过程中首先选择手游 — 既然如此，触摸控制是不可少的。我们将在本教程中了解怎样简单地在移动端 H5 游戏中实现触摸控制，只要移动端支持触摸，你就可以尽情的玩。

**说明**：游戏 Captain Rogers: Battle at Andromeda 是基于Phaser 和 Phaser-based 管理控制，但它也可以用纯 JavaScript 实现。使用 Phaser 的好处它提供了辅助变量和方法可以直接调用，有助于快速的开发游戏，这需要根据项目实际情况选择。

纯 JavaScript 方式实现
-----------------

我们可以实现自己的触摸事件 — 给 document 添加事件监听，并传入自定义功能的方法，非常简单：

```js
var el = document.getElementsByTagName("canvas")[0];
el.addEventListener("touchstart", handleStart);
el.addEventListener("touchmove", handleMove);
el.addEventListener("touchend", handleEnd);
el.addEventListener("touchcancel", handleCancel);
```

这样，在移动设备上屏幕上触摸游戏的 `<canvas>` 将触发这些事件，因为我们就可以随意操控游戏（如：移动太空船）。事件如下所示：

* touchstart 当用户手指放在屏幕上触发。
* touchmove 当他们在屏幕上移动手指时触发。
* touchend (en-US) 当用户在屏幕上停止移动时触发。
* touchcancel 触摸被取消是触发，例如当用户将他们的手指移动到屏幕之外时。

**备注：** 这篇 touch events 参考文章提供了更多的实例和介绍。

### 纯 JavaScript 示例

这个实现了移动端触摸的little demo代码已经放到了 GibHub 上，我们下载这个示例就可以实现在移动端屏幕上移动飞船。

我们将两种事件：`touchstart` 和`touchmove` 放到一个方法里处理。为什么呢？ `touchHandler` 方法定义的飞船位置变量适合下面两种情况下：当玩家触摸时，但不移动它（`touchstart`）和当手指在屏幕上开始移动（`touchmove`）：

```js
document.addEventListener("touchstart", touchHandler);
document.addEventListener("touchmove", touchHandler);
```

`touchHandler` 方法的代码如下：

```js
function touchHandler(e) {
  if (e.touches) {
    playerX = e.touches[0].pageX - canvas.offsetLeft - playerWidth / 2;
    playerY = e.touches[0].pageY - canvas.offsetTop - playerHeight / 2;
    output.innerHTML = "Touch: " + " x: " + playerX + ", y: " + playerY;
    e.preventDefault();
  }
}
```

If the touch occurs (`touches` object is not empty), then we will have all the info we need in that object. We can get the first touch (`e.touches[0]`, our example is not multitouch-enabled), extract the `pageX` and `pageY` variables and set the player's ship position on the screen by subtracting the Canvas offset (distance from the Canvas and the edge of the screen) and half the player's width and height.

![Touch controls for the player's ship, with visible output of the x and y position.](/zh-CN/docs/Games/Techniques/Control_mechanisms/Mobile_touch/controls-touch.png)

To see if it's working correctly we can output the `x` and `y` positions using the `output` element. The `preventDefault()` function is needed to prevent the browser from moving — without it you'd have the default behaviour, and the Canvas would be dragged around the page, which would show the browser scroll bars and look messy.

Touch events in Phaser
----------------------

We don't have to do this on our own; frameworks like Phaser offer systems for managing touch events for us — see managing the touch events.

### Pointer theory

A pointer represents a single finger on the touch screen. Phaser starts two pointers by default, so two fingers can perform an action at once. Captain Rogers is a simple game — it can be controlled by two fingers, the left one moving the ship and the right one controlling the ship's gun. There's no multitouch or gestures — everything is handled by single pointer inputs.

You can add more pointers to the game by using; `this.game.input.addPointer` up to ten pointers can be managed simultaneously. The most recently used pointer is available in the `this.game.input.activePointer` object — the most recent finger active on the screen.

If you need to access a specific pointer, they are all available at, `this.game.input.pointer1`, `this.game.input.pointer2`, etc. They are assigned dynamically, so if you put three fingers on the screen, then, `pointer1`, `pointer2`, and `pointer3` will be active. Removing the second finger, for example, won't affect the other two, and setting it back again will use the first available property, so `pointer2` will be used again.

You can quickly get the coordinates of the most recently active pointer via the `this.game.input.x` and `this.game.input.y` variables.

### Input events

Instead of using the pointers directly it is also possible to listen for `this.game.input` events, like `onDown`, `onUp`, `onTap` and `onHold`:

```js
this.game.input.onDown.add(itemTouched, this);

function itemTouched(pointer) {
  // do something
}
```

The `itemTouched()` function will be executed when the `onDown` event is dispatched by touching the screen. The `pointer` variable will contain the information about the pointer that activated the event.

This approach uses the generally available `this.game.input` object, but you can also detect the actions on any game objects like sprites or buttons by using `onInputOver`, `onInputOut`, `onInputDown`, `onInputUp`, `onDragStart`, or `onDragStop`:

```js
this.button.events.onInputOver.add(itemTouched, this);

function itemTouched(button, pointer) {
  // do something
}
```

That way you'll be able to attach an event to any object in the game, like the player's ship, and react to the actions performed by the user.

An additional advantage of using Phaser is that the buttons you create will take any type of input, whether it's a touch on mobile or a click on desktop — the framework sorts this out in the background for you.

### Implementation

The easiest way to add an interactive object that will listen for user input is to create a button:

```js
var buttonEnclave = this.add.button(
  10,
  10,
  "logo-enclave",
  this.clickEnclave,
  this,
);
```

This one is formed in the `MainMenu` state — it will be placed ten pixels from the top left corner of the screen, use the `logo-enclave` image, and execute the `clickEnclave()` function when it is touched. This will work on mobile and desktop out of the box. There are a few buttons in the main menu, including the one that will start the game.

For the actual gameplay, instead of creating more buttons and covering the small mobile screen with them, we can use something a little bit different: we'll create invisible areas which respond to the given action. From a design point of view, it is better to make the field of activity bigger without covering half of the screen with button images. For example, tapping on the right side of the screen will fire the weapon:

```js
this.buttonShoot = this.add.button(
  this.world.width \* 0.5,
  0,
  "button-alpha",
  null,
  this,
);
this.buttonShoot.onInputDown.add(this.goShootPressed, this);
this.buttonShoot.onInputUp.add(this.goShootReleased, this);
```

The code above will create a new button using a transparent image that covers the right half of the screen. You can assign functions on input down and input up separately if you'd like to perform more complicated actions, but in this game touching the right side of the screen will simply fire the bullets to the right — this is all we need in this case.

Moving the player could be managed by creating the four directional buttons, but we can take the advantage of touch screens and drag the player's ship around:

```js
var player = this.game.add.sprite(30, 30, "ship");
player.inputEnabled = true;
player.input.enableDrag();
player.events.onDragStart.add(onDragStart, this);
player.events.onDragStop.add(onDragStop, this);

function onDragStart(sprite, pointer) {
  // do something when dragging
}
```

We can pull the ship around and do something in the meantime, and react when the drag is stopped. Hauling in Phaser, if enabled, will work out of the box — you don't have to set the position of the sprite yourself manually, so you could leave the `onDragStart()` function empty, or place some debug output to see if it's working correctly. The `pointer` element contains the `x` and `y` variables storing the current position of the dragged element.

### Dedicated plugins

You could go even further and use dedicated plugins like Virtual Joystick — this is a paid, official Phaser plugin, but you can find free and open source alternatives. The initialization of Virtual Joystick looks like this:

```js
this.pad = this.game.plugins.add(Phaser.VirtualJoystick);
this.stick = this.pad.addStick(30, 30, 80, "generic");
```

In the `create()` function of the `Game` state we're creating a virtual pad and a generic stick that has four directional virtual buttons by default. This is placed 30 pixels from the top and left edges of the screen and is 80 pixels wide.

The stick being pressed can be handled during the gameplay in the `update` function like so:

```js
if (this.stick.isDown) {
  // move the player
}
```

We can adjust the player's velocity based on the current angle of the stick and move him appropriately.

摘要
--

这篇文章主要讲解如何在移动端实现触摸控制; 下一篇文章我们将看到怎样添加键盘和鼠标支持。

* Overview: Control mechanisms
* 下一页  (en-US)


Game distribution - 游戏开发

Game distribution
=================

你已经跟着一两个教程 (en-US)做了一个 HTML5 游戏了——真棒 ! 这篇文章介绍了一些可以让你投放你的游戏的方式。包括自己建立网站，在公开的应用市场上线，或是发布到 Google Play 或 IOS 的 App Store。

HTML5 相较于传统的好处
--------------

用 HTML5 构筑游戏有许多好处，例如

### 多平台兼容

HTML5 本身是多平台的，所以你只需要写一种代码就可以适配不同的平台。从小型的智能手机和平板电脑，到笔记本电脑和台式电脑，再到智能电视，智能手表甚至是智能冰箱（如果它内置现代化浏览器的话）。

你并不需要数个开发小组去编写不同平台的代码，你们只需要维护这一种基础代码。你可以花更多时间去推广游戏 (en-US)和促进游戏收益化 (en-US)。

### 即时更新

你不需要花数日去上传你的游戏代码.。如果你发现了漏洞，你可以立即修复它，升级系统和在服务端上传代码以为你的用户更新游戏几乎都是即时的

### 直连，直玩

若是 HTML5 游戏，你无需让大家去应用商店搜索，只需要给他们 URL 链接即可，他们点击链接就可以直接玩游戏，而不需要使用第三方平台或是下载一个很大的安装包来安装游戏。不过你仍需考虑你的游戏的大小是否可能会让用户花一点时间来加载资源，以及你的游戏对网速的需求。总之，如果你把你的游戏按照你的设想构建，并且在开玩之前没有那么多弯弯绕绕，推广它还是很容易的

电脑还是手机？
-------

我们感兴趣的绝大部分流量——HTML5 游戏玩家——都来自移动设备，所以如果你真的想要成功，你就必须专注于这一点。手机端是 HTML5 真正发光发热的地方，那里没有 Flash，HTML5 便是全部。

要与 PC 端游直接竞争是很困难的，当然你也可以在 PC 端发布你的游戏（见下文的电脑平台）你也应该这么做，因为这可以让你的游戏支持的平台变得多样化，但谨记，电脑游戏的开发者拥有多年的经验，优秀的工具和稳定的发行渠道。许多 HTML5 游戏会与传统电脑游戏面向不同的受众市场。例如，简单的的小游戏比大型的沉浸式游戏更有人气，这类游戏通常设计成用两根手指，甚至一根手指玩，所以你可以拿着设备玩游戏，还可以用第二只手做你目前需要的任何事情。

话又说回来，电脑平台易于发行游戏，因为有许多好用的打包软件帮助你构造游戏的架构（见下文游戏打包），为你的游戏配置适应电脑端的控制器也是很不错的做法——即使你的游戏主要面向手机用户。用户可以在任何平台畅玩你的游戏，电脑端也应该是其中之一。此外，在电脑端先构建和测试游戏通常更为便捷，然后再到手机端测试 BUG

发布游戏
----

当你要发行游戏时，通常有三种主要的方式可供选择

* 自运营
* 发行商代理
* 上架商店

记住你的游戏名应该要足够独特，这样可以在发布之后迅速地推广 (en-US), 但也要同样朗朗上口，这样人们才不会忘记。

### 自运营

如果你是前端开发者，你应该已经知道要做什么了。一个 HTML5 游戏不过是又一个网站而已.。你可以将它上传到远程服务器，设置一个好记的域名，然后就可以自己开始运营游戏了。

如果你想从游戏开发中赚钱，你应该用多种方法保护你的源码，这样其他人不会轻易地取得你的源码并且拿去当成自己的去出售。你可以压缩和精简代码，让它变得更小，更难读，这样他人就不能轻易的复刻你的游戏。一个更好的方法是在网上发布测试版如果你打算打包你的项目并把它出售给 Steam 或者 iTunes。

如果你只是为了娱乐性质的话，开放源码可以让那些想要从你的作品中学习的人收益。你甚至不需要担心主机提供商，因为你可以在 Github 上托管游戏. 你可以有一个免费的主机，可控制的版本，以及可能的贡献者——如果这个项目足够有趣的话。

### 发行商和门户网站

顾名思义，开发商可以帮助你发行游戏，是否交给开发商则取决于你的游戏开发计划：你想在全平台发行么？或你只向购买了游戏的用户开放游戏？这都取决于你，考虑各个选项，试验和结论。你可以在游戏收益化这篇文章中得到更详细的关于发行商的解释。

这里还有许多独立的门户网站收集 HTML5 游戏，例如 HTML5Games.com, MarketJS.com, Clay.io, or Poki 你可以把你的游戏发布上去，它会得到一些自然的推广，因为这些网站吸引了大量的流量。一些网站会把你的文件放在他们的服务器上运营，而其他网站则只链接到你的网站或将你的游戏嵌入他们的网站，这样的曝光可能只是为你的游戏提供宣传，如果你的游戏旁边有广告 (或其他赚钱的选项)，它也可能为你的游戏提供收益化。

### 网络和应用商店

你也可以直接把游戏发布到不同的应用商店里，或者是应用市场，要做到这一点，你必须准备好并将其打包为针对你想要针对的每个应用程序生态系统的特定构建格式。见下文应用市场—多样化平台来获取更多关于应用市场的细节

应用市场—多样化平台
----------

让我们看看针对不同平台和操作系统的市场/商店有哪些可用选项。

**备注：** 这些是最流行的发行平台，但这并不是说这些是唯一的选择。你也可以尝试找到一个对口的平台，并直接向那些对你的游戏感兴趣的观众推广你的游戏。在这里，你的创造力至关重要。

### 网络商店

最适合 HTML5 的平台是基于 web 的商店。为它们准备一款游戏很容易，因为这样的操作几乎不需要修改游戏本身——通常在包含所有资源的压缩包中添加包含必要信息的清单文件就足够了。

* Firefox OS 是 HTML5 游戏的完美硬件平台，因为系统本身是用 JavaScript 编写的，而且是开源的。你可以快速访问控制硬件的核心应用程序，Firefox Marketplace 是推广你的游戏的好地方，你也可以更进一步，允许人们直接从网络上安装你的游戏。
* The Chrome Web Store 也是一个吸引人的选择——同样，准备好一个清单文件，压缩你的游戏并填写在线提交表单就足够了。
* Tizen 还高度重视支持用 JavaScript 编写的应用程序。他们的商店是另一个可用的选择。
### 手机应用商店

在移动市场上，iOS 版的苹果应用商店 (Apple App Store)、Android 版的谷歌 Play 以及其他竞争对手。原生商店中已经充斥着销售优秀游戏的成熟开发者，所以你必须具备足够的天赋和幸运才能获得关注。

* iOS App Store 很难进入，因为游戏必须满足严格的要求，你必须等待一到两周才能被接受。此外，它是最著名的移动商店，有成千上万的应用程序，所以很难从人群中脱颖而出。
* Google Play's 的要求不那么严格，所以商店被低质量的游戏污染了。由于每天提交的应用程序数量庞大，因此很难被注意到。在这里赚钱也更加困难——大多数来自 iOS 的付费游戏都是在 Android 上作为免费游戏发布的，盈利来自于应用内购买 (IAPs) 或广告。
* 其他面向 Windows Phone 或黑莓 (Blackberry) 等本土移动平台的商店也在努力分一杯羹，而且远远落后于竞争对手。在那里提交你的游戏是很好的，因为它会更容易被注意到。

如果你想了解更多关于不同类型的应用程序商店的信息，你可以在维基百科上查看手机软件发布平台列表。

### 电脑平台

为了扩大你的受众，你也可以使用 HTML5 游戏去占据电脑游戏市场——只要记住那些已经占据了大部分市场份额的 AAA 级游戏，并仔细考虑这是否适合你的策略。要正确的在电脑端运行，你应该支持所有三种操作系统:Windows、Mac OS 和 Linux。最大的电脑游戏商店无疑是Steam — 独立开发者可以通过 Greenlight 接触 steam. 请记住，你必须通过为不同的平台上传不同的版本来处理跨平台问题。

在你入驻 Steam 之后，便会有许多类似于Humble Bundle等项目的讨论，这些项目可以把最受欢迎的独立游戏能够呈现给更多人。不过，这更像是一个绝佳的促销机会，而不是一种赚大钱的方式，因为捆绑游戏的价格通常相当低。

打包游戏
----

网页是 HTML5 游戏的首选也是最好的选择，但如果你想接触到更广泛的受众并在封闭的生态系统中发行你的游戏，你仍然可以通过打包它来做到这一点。好在你不需要几个独立的团队在不同的平台上致力于同一款游戏——你可以一次性构建它，并使用像 Phonegap 或 CocoonIO 这样的工具为本地商店打包游戏。生成的包通常非常可靠，但是你仍然应该测试它们，并注意要修复的小问题或 bug。

### 实用工具

根据你的技能、首选框架或目标平台，可以选择多种工具。关键是为你的特定任务选择最好的工具。

* Phonegap —基于 Cordova，这是为本地平台构建/打包 JavaScript 应用程序最流行的工具
* CocoonIO — 为多个本地商店构建 HTML5 游戏的最流行的工具。它对画布上呈现的游戏有自己的性能优化，并支持许多游戏框架。
* Ejecta — 一个专门用于为 iOS 打包使用the ImpactJS框架创建的游戏的工具，由 ImpactJS 作者构建。它提供了与 ImpactJS 的无缝集成，但只支持一个框架和应用程序商店。
* NW.js — 这款游戏的前身是 Node-Webkit，它是开发适用于 Windows、Mac 和 Linux 的桌面游戏的首选。这些发行版与 WebKit 引擎打包在一起，可以在任何平台上提供呈现。

其他替代工具包括：

* Intel XDK — 一个很棒的的替代品，类似 CocoonIO。
* Electron — 或者叫 Atom Shell，是 GitHub 的一个开源跨平台工具。.
* Manifold.js — 微软团队的这个工具可以从 iOS、Android 和 Windows 创建 HTML5 游戏的本地发行版。
总结
--

发行游戏是让你的世界为世界所知的方式，选择很多，但没有上上策。当你发行了游戏之后，便是专注于推广的时候了——让人们知道你的游戏的存在。没有推广，它们甚至都可能不知道有这个游戏，更别说玩了。


游戏货币化 - 游戏开发

游戏货币化
=====

当你花时间创造一个游戏的时候，从发布 (en-US)和促销 (en-US)中赚钱是你应该考虑的事。如果你正做出大量努力去成为一个能够以此为生的独立游戏开发者，接下去，看看你有哪些选择。技术手段已经足够成熟; 接下来只是选择正确的方法。

付费游戏
----

你可能想到的第一个，也是最明显的选择便是以面向 AAA 级游戏的方式销售游戏——即固定的预付款。即使数字市场是关键，你也不需要打印封面，也不需要将游戏放在实体店的盒子里，但要想以固定的价格销售游戏赚取可观的利润，你必须将时间和金钱投入到市场营销中去。只有最好的游戏才能做到收支平衡，或者赚得比制作成本还要多，你仍然需要很多的运气。

你为你的游戏收取多少费用取决于市场，游戏的质量和许多其他小因素。一款街机 iOS 游戏售价为 0.99 美元，但一款更长的 rpg 风格的 Steam 桌面游戏售价为 20 美元;两个价格都可以。你必须跟随市场，做自己的研究——迅速从错误中吸取教训是很重要的。

应用内购买内容
-------

你可以提供一款带有应用内购买功能（IAP）的免费游戏，而不是让人们预先为你的游戏付费。在这种情况下，玩家不需要花一分钱就可以获得游戏——将游戏交给玩家，但要提供游戏内的货币、奖金或福利。具体的例子可以包括奖金水平，更好的武器或咒语，或补充所需的能量发挥。设计一个好的 IAP 系统本身就是一门艺术。

记住，你需要下载数千次游戏才能使 IAPs 有效——只有一小部分玩家会真正为 IAPs 付费。多小？情况各不相同，但大约每千人中就有一个人处于平均水平。玩你的游戏的人越多，别人就越有可能付钱，所以你的收入很大程度取决于你的推广 (en-US)方式。

### 免费增值模式

带有 IAPs 功能的游戏通常被称为免费增值游戏——免费增值游戏可以免费取得与游玩，但你可以为额外的 (高级) 功能、虚拟物品或其他好处付费。在大公司专注于创造游戏后，这个词本身就带有负面含义，其主要目的是为了从玩家那里获得尽可能多的钱，而不是提供一种有趣的体验。最糟糕的情况是，你可以用真金实银来获得相对于其他玩家的优势，或限制玩家进入游戏的下一阶段，除非玩家付费。“为赢付费”这个术语是被创造出来的，并且这种方法不受许多玩家和开发者的欢迎。如果你想要实现 IAPs，那就试着用玩家喜欢的东西来为游戏增加价值，而不是把它拿出来然后收费。

### 扩展包 (Add-on) 和可下载内容 (DLC)

扩展包和可下载内容是为已经发行的游戏提供额外价值的好方法，但请记住，你必须提供体面的、有趣的内容来吸引人们购买它。一套全新的带有新角色、武器和故事的关卡对于 DLC 来说是一个很好的素材，但要想获得足够的销量，游戏本身必须是受欢迎的，否则就不会有玩家愿意将他们辛苦赚来的钱花在这上面。

推广
--

除了积极销售游戏以外，你也可以尝试被动销售 — 投放广告和开展相关活动或许有益于推广 (en-US)你的游戏，但你的游戏必须让人上瘾，这并不像听起来那么容易。你仍然需要计划好，在某种程度上，你也需要一些运气。如果你的游戏像病毒一样传播开来，人们开始分享它，你就能从广告中获得大量的下载和收益。

有许多公司提供广告系统——你注册后，允许他们展示广告，以换取一定比例的利润。谷歌 AdSense 被认为是最有效的一个，但它不是为游戏而设计的，使用它来达到这个目的是一个非常糟糕的做法。不要冒着让你的账户被封禁，资产被冻结的风险，游戏开发者们更青睐门户网站，如LeadBolt。他们提供了易于实现的系统，以在你的游戏显示广告并与你分享收益。

视频广告正变得越来越受欢迎，特别是以预播放的形式——它们会在游戏开始时显示，而此时游戏还在加载中。至于在游戏中放置广告的位置，这完全取决于你自己。它应该尽可能的微妙，以避免过多地惹恼玩家，但又足够的可见性让玩家点击它或至少注意到它。通过屏幕在游戏会话之间添加广告是一种流行的方法。

授权证书
----

有一种方法可以作为自己的盈利模式，即出售游戏发行许可。越来越多的门户网站有兴趣在他们的网站上展示你的游戏。他们遵循各种策略来通过你的游戏赚钱，但你不必担心所有这些，因为出售许可通常是一次性的交易。你得到了钱，他们就可以创造性地使用你的游戏来赚钱。

一开始寻找发行商是件困难的事情 — 你可以在HTML5 Gamedevs forums联络他们.。如果你很有名，他们可能会联系你。大多数交易都是通过电子邮件与出版商一方的专业人士进行沟通的。一些出版商的网站很容易获得这些信息，而另一些则很难找到。当接触出版商的时候，尽量友好而直接——他们都是很忙的人。

### 独家许可

独家性许可是针对一个发行商的一种许可类型——你创造了一款游戏，并将其所有权利出售给了一个实体，同时还拥有重新发行该游戏的权利 — Softgames就是这样一家发行商。在出版商拥有版权的情况下，你不能再以任何形式出售它——这就是独家交易价值不菲的原因。到底是多少？这取决于游戏的质量，游戏类型，发行商，以及其他许多因素，但通常价格在 2000 到 5000 美元之间。一旦你卖出了独家授权，你就不用再参与推广这款游戏了，因为你赚不到更多钱，所以只有在你确信这款游戏足够盈利的情况下，你才会参与这样的交易。

### 非独家许可

这种方法不那么严格——你可以将许可证出售给多个发布者。这是最受欢迎的方法，因为对于每一个新的发行商 (总会有的)，你都可以以非独家的条款出售你的游戏。请记住，有了这个许可，发行商就不能再对其进行重新发行了——这通常被称为站点锁定交易，因为他们购买了在自己的门户网站上发布游戏的权利。非独家许可的通常成本约为 500 美元。

### 定期付费

此外，用户还可以通过购买服务来月付你的游戏而不是一次性付款，每一款游戏每月都能为你提供一定的钱——大约 20-50 美元。你可以决定是一次性付清一段时间还是每月付一次。记住它可以被随时取消，所以它不是一个通解。

### 推广收入

你可以在自己的游戏中发布广告，并试图找到流量来赚取一些钱，但你也可以与发行商达成收益分成协议。他们将负责吸引流量，并将分享收益——通常是每月 73 开或者五五开的交易。

请记住，许多新的、低质量的发行商会希望你的游戏获得广告收入而不是授权，因为这对他们来说更便宜，并且你可能只会在整个交易中获得每款游戏约 2 美元的收益。在与新出版商打交道时要小心——有时候，降低已知出版商的许可成本比冒着被未知出版商骗钱的风险要好。

发行商从你的游戏中获取收益分成，以及/或许可可能需要实现他们自己的 API，这可能需要额外的工作，所以你也要考虑到这一点。

### 品牌

你可以出售你的游戏的品牌使用权，也可以用你自己的游戏来招揽其他人的品牌。在第一种情况下，它几乎类似于非独占许可，但是你的客户通常会购买代码的权限并构建自己的游戏。在第二种情况下，它就像一个自由的交易，但你将会在代码中加入客户的品牌图形，或有时会按照他们的指示实现需求。举个例子，如果你有一个游戏，玩家点击食物，你可以把食物换成客户的产品来给他们做广告。这个模型中的价格根据品牌、客户和工作量的不同而有很大的差异。

其他不以游戏为主题的变现手段
--------------

在开发 HTML5 游戏时，你还可以通过其他方式赚钱，而这甚至不需要与游戏相关。

### 销售资源

如果你是一名平面设计师，你可以出售你所创造的游戏的资产，或一些全新的专为这一目的的在线商店，如Envato Market. 虽然卖的钱并不多，但如果你是一个著名的设计师，它就是一个额外的被动收入流。

### 撰写文章和教程

你可以写一些关于你的游戏的文章，甚至可以从中获得报酬。可以同时取得游戏推广 (en-US)和收益化的双赢，如果你不滥用它与太多的广告，读者将享受阅读他们以及学习一两个东西。如果你专注于先分享知识，并将游戏作为例子来使用，这应该是可以的。浏览Tuts+ Game Development 或相似的网站来找寻协作机会

### 周边商品

你可以售卖 T 恤，贴纸或其他周边 — 有些开发者从这些商品中赚的钱比从游戏本身中赚的钱还多，但它只适用于像愤怒的小鸟这样非常受欢迎且易于识别的游戏。不过，这也可能是另一种小的被动收入来源。你的收入越多样化，你的生意就越稳定。

### 捐助

当其他方法都失败时，你可以尝试在你的游戏页面上放置一个捐赠按钮并寻求社区的支持。有时候它是有效的，但前提是玩家了解你并觉得它能够帮助你。这就是为什么小心管理你的社区是如此重要。这在js13kGames比赛中很管用 — 每个参与者都得到了一件免费的 t 恤，有些人甚至还退了一些钱，以帮助它在未来几年继续运行下去。

小结
--

赚钱的方法有很多种——所有适用于“普通”AAA 级游戏世界的东西，或多或少都可以应用于休闲 HTML5 游戏。然而，你也可以专注于销售许可证，做品牌，或者从广告中获得收入分成。你要走哪条路完全取决于你自己。


Game promotion - 游戏开发

Game promotion
==============

开发与发行你的游戏并不是全部.。你应该让大家知道你有个大家会喜欢玩的游戏。这儿有很多方法去推广你的游戏——大部分方法是免费的，所以即使即使你正努力以一名零预算的独立开发者的身份谋生，你也可以让人们知道你的新游戏.。推广游戏也对之后的游戏收益化 (en-US)大有裨益，所以正确地推广游戏是很重要的。

竞赛
--

 参加竞赛不仅将提升你的游戏开发技能，让你认识新朋友、学习开发，它还将让你参与到社区之中。如果你在比赛中做了一个好的游戏并赢得了一些奖品，你的游戏就会自然而然地被组织者和其他参与者推广开来。你会变得富有和出名，至少他们是这么说的。
 许多优秀的游戏都是从一个游戏制作比赛上的 demo 开始的。如果你的想法和执行力都足够好，你就会成功。另外，比赛通常要求游戏有一个固定的主题，所以如果你一筹莫展，你也可以围绕这个主题进行创作。

网站与博客
-----

你应该创建自己的网站，包含所有关于游戏的信息，这样人们就可以看到你在做什么。你能包含的信息越多越好 — 包括截图，简报，预告，宣传资料，需求，可用的平台，赞助以及其他。让你的用户在网上直接玩你的游戏——或者说测试版可以让你得到许多电子。同时，为了让你的用户能够更好的玩游戏，你应该做些网站优化（SEO）

你也应该在博客公布所有与你游戏开发有关的动作，写下你的开发历程，严重的 bug，有趣的事情，经验教训，以及作为游戏开发者的起起伏伏。坚持发布信息有助于他人从中学习，提高你在社区中的声誉，改进你的网站优化。另一种选择是发布每月报告——总结你所有进展的报告——它能够帮助你看到你在整个月都完成了什么，还有什么需要去做，并不断提醒人们你的游戏即将发行——创造口碑总是好的。

社交媒体
----

你的社交媒体的风格很重要 — 选择正确的标签，交朋结友，参与交流，帮助其他开发者。保持真诚，这是你与人结交的关键，因为没有人喜欢无聊的新闻发布或者硬广告.。一旦游戏完成，你的社区会帮助你宣传你的小宝贝游戏的

你应该至少使用推特（Twitter）和脸书（Facebook）之中的一个，并且入驻一个合适的论坛，最出名的就是 HTML5GameDevs.com. 分享你的游戏开发信息，回答别人的问题，这样人们会在心里衡量你所做的一切并且知道你做的很好.。记住也别逢人就说你的游戏——你可不是行走的广告

发展你的粉丝，你可以与他们交流，分享一些小贴士，提供一些福利，在比赛中分发奖品，或者只是抱怨天气或者浏览器的问题，举止冷静，慷慨大方，做你自己，去帮助别人，你就会得到尊重。

游戏门户网站
------

设立门户网站主要与收益化 (en-US)挂钩，但是如果你不打算售卖许可 (en-US)来让人们可以购买你的游戏而是打算发布广告 (en-US) , 在免费的门户网站上推广游戏会更有效。你可以在公共门户网站，比如HTML5Games.com发布游戏，比起传统的游戏发行平台，它更像一个宣传平台。

免费的门户网站带来了流量，但是，只有最好的广告才足够受欢迎，能够从发布的广告中获得一些业绩。另一方面，如果你没有预算和有限的时间，门户网站也是一个完美的工具，它可以让更多人看到你的游戏

媒体宣传
----

你可以试着联系媒体去宣传你的游戏，不过要记住，他们每天都在处理成吨的请求，所以如果它们没有及时回复你，请保持耐心，在于他们交流时保持礼貌。一定要先检查他们是否只接纳特定类型的游戏或平台，这样你才不会发送与之无关的内容。如果你方式恰当并且你的游戏很好，那么你就有更多的成功机会

如果你想了解更多关于联系媒体的礼仪，你可以阅读 How To Contact Press - 由 Pixel Prospector 编写的一篇很棒的指南，还有Video Game Journaliser，他们创建的一个记录媒体联络名单的网站。

教程
--

与其他开发者互通有无是很好的 — 毕竟你可能也曾在网上的一两篇文章上学到了些东西，所以你要花时间把这些知识传递出去。谈论或写一些你取得的成就或克服的问题是人们会感兴趣的事情。你可以拿你自己的游戏做例子，特别是当你展示你已经实现的事情. 这样每个人都会受益——人们学习新的技能，你的游戏会得到推广，如果你足够幸运，你甚至可以因为编写教程而获得报酬

像是Tuts+ Game Development 这样的网站可能会更让人开心——他们为文章付稿费。但并不是所有的主旨都会被接受。当你在写教程的时候，记住要把重点放在给读者提供一些有价值的东西上。他们想要学习一些东西——提供你的专业知识并将你的游戏作为案例研究。专注于一个方面，并试图解释它的全部和细节。如果人们有任何问题，请记得在评论中跟进讨论。

如果你联系的门户网站因你未写过教程而未采纳你的教程，可以在自己的博客先发布教程，这是锻炼你的写作技巧的最简单的方式。

YouTuber 视频主 (YouTubers)
------------------------

这是一种趋势 — 别低估了 YouTuber 视频主（YouTubers）们对游戏的影响力，与他们交流，让他们做游戏实况会极大的宣传你的游戏。不过，你也应该现实一点——不要认为仅仅这一点就会让你的下载量或访问量飙升，而且要准备好处理好不好的评论。

有两种方法可以让 Youtubers 选择你的游戏：第一种方法是你直接联系他们，并通过电子邮件或私人信息向他们发送游戏链接。第二种方法更省时 - 如果你很有名，Youtubers 可能会向你索要游戏链接或游戏文件。这个YouTuber 的名单是个很好的开始。

活动
--

如果你已经完成了上面列出的所有选项，你仍然可以找到新的、创造性的方式去推广你的游戏——活动便是另一个很好的例子。参加本地和全球的活动，让你能够面对面地与你的粉丝以及开发社区的其他成员见面。别辜负了他们专程花时间来看你的心思。.

### 会议

在许多会议上，你可以发表演讲，解释你克服的一些技术困难，或者如何实现特定的 API;其次，以你的游戏为例。专注于知识部分并降低市场营销是很重要的——开发者对这个问题很敏感，如果你只是想向他们推销一些东西，他们可能会对此不满。.

### 展会

另一个与活动相关的选项是展会 (或博览会)——在这样的活动中，你可以在其他开发者中获得一个摊位，并向所有经过的参与者推广你的游戏。如果你这样做了，那就试着做得独特而有创意，这样你就很容易从人群中脱颖而出。以正确的方式去做，每个人都会谈论你和你的游戏。有一个展台可以让你与你的粉丝直接互动——除了推广部分，你还可以在普通人身上测试你的游戏的新版本，并修复他们发现的任何 bug(或包含任何反馈)。你无法想象人们在玩你的游戏时可能会想到什么，以及你在花费数小时打磨游戏时错过了哪些明显的问题。

优惠码
---

如果你是在销售游戏，那么你应该发行优惠码让人们免费游玩你的游戏 (或至少是一个演示版或限时版)，并把它们发送到各地——给媒体，Youtuber，作为比赛奖品等等。如果游戏符合某些人的胃口，就相当于为成千上万人打了一次免费广告。如果你幸运的话，它比任何其他东西都能提高人们对你的游戏的兴趣

培养社区
----

你可以帮助社区成长，同时推广你自己和你的游戏。发布每周时事通讯，组织在线竞赛或者线下聚会，这些都能让别人知道你对自己的工作充满激情，他们可以依靠你。当你需要帮助的时候，他们会在你身边

总结
--

任何推广你的游戏的方法都是好的。你有很多选择，其中大部分都是免费的，所以关键在于你的热情和可用时间。有时候你不得不花更多的时间去推广一款游戏，而不是真正去开发它。记住，如果没有人知道世界上最好的游戏的存在，那么拥有它是没有任何意义的。

现在让我们进入游戏收益化 (en-US)部分，然后挣口饭吃吧。


附加组件 - Mozilla

附加组件
====

附加组件允许开发者们去扩展和修改 Firefox 的功能。开发者们能使用标准的 Web 技术「JavaScript，HTML 以及 CSS」再加上一些专用的 JavaScript APIs 来开发附加组件。

除此之外，附加组件还能：

* 改变指定网站的外观或者内容
* 修改 Firefox 的用户界面
* 给 Firefox 加上新功能

有几种附件组件类型，但最常见类型是扩展。

开发扩展
----

在过去，有几种工具集用于开发 Firefox 扩展，但是到 2017 年 11 月底，扩展必须使用 WebExtensions APIs 构建。其余工具集「包括 overlay add-ons、bootstrapped add-ons 和 Add-on SDK」将会同时被废弃。

使用 Firefox WebExtensions APIs 编写的扩展设计为跨浏览器兼容。在大多数情况下它也能在 Chrome，Edge 和 Opera 中运行，几乎没有任何变化。它们也完全兼容多进程 Firefox。你可以查看目前在 Firefox 和其他浏览器中支持的 APIs。

### 扩展工坊

Firefox 扩展工坊可以帮助你为 Firefox 开发扩展，并为你的用户提供简单而强大的方式来定制他们的浏览体验。你会找到：

* Firefox 扩展特征概述
* 开发和测试工具及其流程
* 如何在 addons.mozilla.org 上发布扩展或自己分发扩展
* 如何管理已发布的扩展
* 对于企业用户，开发和使用扩展的指南
* 如何为 Firefox 开发主题
* Firefox 开发者社区
### Android 版 Firefox 的扩展

2020 年，Mozilla 将发布一款新的 Android 版 Firefox。这款新的 Android 高性能浏览器是使用 Mozilla 的移动浏览器引擎 GeckoView 从头开始重新构建的。我们目前正在 GeckoView 上添加对 WebExtensionsAPI 的支持。

### 迁移现有扩展

如果你正在维护一个旧式扩展，比如 XUL overlay、bootstrapped，或者基于 Add-on SDK 的扩展，我们建议你将其移植到 WebExtension APIs。这里有一些Firefox 扩展工坊中的移植资源。

有关过渡支持的更多内容，请访问我们的wiki 页面。

发布附加组件
------

Addons.mozilla.org，俗称「AMO」，是 Mozilla 官方的官方站点，方便开发者发布扩展组件和用户查找。通过上传附加组件到 AMO，你可以加入我们的用户和开发者社区，为你的附加组件找到订阅者。

你不一定需要在 AMO 上发布你的附加组件，但你的附加组件必须要经过 Mozilla 签名，否则用户不能安装它。

有关发布附加组件过程的概述，请参阅签署和分发你的加载项。

其他类型的附加组件
---------

通常，当人们谈起附加组件时是指扩展工具，但是这里也有一些其他类型的附加组件允许用户定制 Firefox. 这些附加组件包括：

* 用户字典 是可以进行各种语言的拼写检查的插件；
* 语言包 让你有更多可用的语言用于 Firefox 的界面。
联系我们
----

查看联系我们页面，了解有关如何获得帮助、时刻关注关于附加组件的最新消息以及向我们提供反馈的详细信息。


Firefox - Mozilla

Firefox
=======

Firefox（非正式中文名称“火狐”）是 Mozilla 的流行 Web 浏览器，适用于多种平台，包括 Windows、MacOS、Linux 等桌面版，以及所有的 Android 和 iOS 移动设备。得益于对最新的 Web 标准的广泛兼容性和强有力的开发工具，Firefox 是 Web 开发者和终端用户的绝佳选择。

Firefox 是一个开源项目，许多代码都是由庞大的志愿者社区贡献的。在此你可以了解如何为 Firefox 项目做贡献，你也可以找到关于构建 Firefox 附加组件、使用 Firefox 开发者工具以及其他主题的信息的链接。

了解如何为 Firefox 创建附加组件、如何开发和构建 Firefox 本身，并了解 Firefox 的内部以及其他子项目如何运作。

主要资源
----

Firefox 开发者指南

我们的开发者指南提供了关于获取 Firefox 源代码，在 Linux、macOS 和 Windows 上构建源代码，如何找到解决方法，以及如何为项目做贡献的详细说明。

Firefox 附加组件指南

附件组件指南提供了开发和部署 Firefox 扩展的信息。

面向开发者的发布说明

在面向开发者的发布说明中了解每一个 Firefox 版本为网站与附加组件开发者带来的新功能。

Firefox 更新通道
------------

Firefox 通过 5 个**更新通道**进行发布。

### Firefox Nightly

每天晚上，我们都使用 mozilla-central 中的最新代码构建 Firefox。这些版本适用于开发者或想要尝试最新的、处于活跃开发中的特性的使用者。

下载 Firefox Nightly

### Firefox 开发者版

这是一个为开发者量身定做的 Firefox 版本。Firefox 开发者版拥有所有已经达到测试版（beta）的最新的开发者工具。我们还为开发者添加了一些额外的、仅在这个更新通道提供的特性。它使用自己的路径和配置文件，因此它可以与标准版或 Beta 版 Firefox 一起运行。

下载 Firefox 开发者版

### Firefox Beta

每隔四个星期，我们就会选取足够稳定的特性，创建一个新的 Firefox Beta 版本。Firefox Beta 版是为 Firefox 爱好者提供的，用于测试注定会成为下一个 Firefox 标准版本的内容。

下载 Firefox Beta

### Firefox

当在 Beta 频道中稳定四周之后，我们便发布 Firefox 的新版本，将新特性推送至数亿用户。

下载 Firefox

### Firefox 延长支持版（ESR）

Firefox 延长支持版是在较长周期提供支持的桌面版 Firefox，适用于学校、大学、商业机构等组织以及需要延长支持用以进行大规模部署的用户。

下载 Firefox 延长支持版

内容
--

Firefox 中的实验性特性本页列出了 Firefox 的实验性和部分实现的特性，包括针对提议的或前沿的网络平台标准的特性，以及这些特性的版本信息、是否“默认”激活这些特性，以及可用于激活或停用这些特性的偏好设置。这样，就可以在特性发布前对其进行测试。

与 Firefox 开发者相关的发行说明本页提供每个 Firefox 的版本的“与 Firefox 开发者相关的发行说明”文章的链接。这些日志文章可以让你查看每个 Firefox 版本增加了哪些功能和修复的错误。

参见
--

* 邮件列表
* 发布时间表


Firefox 中的实验性特性 - Mozilla

Firefox 中的实验性特性
===============

本页列出了 Firefox 的实验性和部分实现的特性，包括针对提议的或前沿的网络平台标准的特性，以及这些特性的版本信息、是否“默认”激活这些特性，以及可用于激活或停用这些特性的偏好设置。这样，就可以在特性发布前对其进行测试。

新特性首先出现在 Firefox Nightly 版本中，通常默认启用。它们随后会引入到 Firefox 浏览器开发者版，并最终引入到发布版本中。在发布版中默认启用某项特性后，该特性就不再被视为实验性特性，应从主题中删除。

可以使用 Firefox 配置编辑器（在 Firefox 地址栏中输入 `about:config`）通过修改下面列出的相关首选项来启用或禁用实验特性。

**备注：** 对编者的信息——当在这些表格添加特性时，请尝试使用 `[Firefox bug <number>](https://bugzil.la/<number>)` 包含指向相关 bug 的链接。

HTML
----

### input type="search" 外观

输入类型 `type="search"` 的布局已更新。一旦有人开始输入，搜索字段就会有一个清晰的图标，以便与其他浏览器的实现相匹配。（详情请参见 Firefox bug 558594）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 81 | 否 |
| 开发者版 | 81 | 否 |
| Beta | 81 | 否 |
| 发行版 | 81 | 否 |
| 首选项名称 | `layout.forms.input-type-search.enabled` |

### 切换密码显示

HTML 密码输入元素（`<input type="password">`）包含一个“眼睛”图标，可通过切换来显示或遮盖密码文本（Firefox bug 502258）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 96 | 否 |
| 开发者版 | 96 | 否 |
| Beta | 96 | 否 |
| 发行版 | 96 | 否 |
| 首选项名称 | `layout.forms.input-type-show-password-button.enabled` |

### ARIA 属性反射

为非 IDREF 属性启用了 ARIA 反射特性，允许作者通过 JavaScript API 直接获取和设置 DOM 元素上的 ARIA 属性，而不是使用 `setAttribute` 和 `getAttribute`（详情请参见 Firefox bug 1824980）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 114 | 是 |
| 开发者版 | 114 | 否 |
| Beta | 114 | 否 |
| 发行版 | 114 | 否 |
| 首选项名称 | `accessibility.ARIAReflection.enabled` |

CSS
---

### 显示杂散控制字符的十六进制框

该特性会将除*制表符*（`U+0009`）、*换行符*（`U+000A`）、*换页符*（`U+000C`）和*回车符*（`U+000D`）以外的控制字符（Unicode 类别 Cc）渲染为十六进制框，而这些控制字符并非预期字符。（详见 Firefox bug 1099557）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 43 | 是 |
| 开发者版 | 43 | 否 |
| Beta | 43 | 否 |
| 发行版 | 43 | 否 |
| 首选项名称 | `layout.css.control-characters.enabled` 或 `layout.css.control-characters.visible` |

### initial-letter 属性

`initial-letter` (en-US) CSS 属性是 CSS Inline Layout 规范的一部分，允许指定如何显示下垂、凸起和下沉的首字母。（详情请参见 Firefox bug 1223880）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 50 | 否 |
| 开发者版 | 50 | 否 |
| Beta | 50 | 否 |
| 发行版 | 50 | 否 |
| 首选项名称 | `layout.css.initial-letter.enabled` |

### content-visibility: auto 值

如果内容不与用户相关，`content-visibility` CSS 属性值 `auto` 允许跳过渲染。（详见 Firefox bug 1798485）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 113 | 是 |
| 开发者版 | 109 | 否 |
| Beta | 109 | 否 |
| 发行版 | 109 | 否 |
| 首选项名称 | `layout.css.content-visibility.enabled` |

请注意，相关的 `contentvisibilityautostatechange` 事件和相关的 `ContentVisibilityAutoStateChangeEvent` 接口是在版本 110 中添加的，并由相同的首选项控制。应用程序代码可使用这些特性监控可见性变化，并在用户代理跳过元素内容时停止与渲染元素相关的进程。（详见 Firefox bug 1791759。）

### 在媒体查询中将单个数字作为纵横比

在为媒体查询指定宽高比时，支持将单个 `<number>` 用作 `<ratio>` 。（详见 Firefox bug 1565562）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 70 | 否 |
| 开发者版 | 70 | 否 |
| Beta | 70 | 否 |
| 发行版 | 70 | 否 |
| 首选项名称 | `layout.css.aspect-ratio-number.enabled` |

### backdrop-filter 属性

`backdrop-filter` 属性会对元素后面的区域应用过滤效果。（详情请参见 Firefox bug 1178765）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 70 | 否 |
| 开发者版 | 70 | 否 |
| Beta | 70 | 否 |
| 发行版 | 70 | 否 |
| 首选项名称 | `layout.css.backdrop-filter.enabled` |

### CSS 函数 ray()

CSS `ray()` (en-US) 函数是定义 `offset-path` (en-US) 的一种方法。该函数将路径定义为从 `offset-position` (en-US) 开始并向指定角度方向延伸的线段（Firefox bug 1582554）。

在版本 112 中，该函数添加了 `<ray_size>` 可选参数。如果没有提供 `<ray_size>`参数，该函数将默认使用 `closest-side` 值（Firefox bug 1820071）。

在版本 116 中，该函数增加了 `at <position>` 可选参数。如果省略，则使用元素的 `offset-position` 值。如果同时没有 `at <position>` 和 `offset-position` 值，则使用 `offset-position: auto` 作为射线的起始位置，将元素置于元素框的左上角。（Firefox bug 1820070）

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 72 | 是 |
| 开发者版 | 72 | 否 |
| Beta | 72 | 否 |
| 发行版 | 72 | 否 |
| 首选项名称 | `layout.css.motion-path-ray.enabled` |

### Masonry grid 布局

新增对基于网格布局的 masonry 风格布局 (en-US)的支持，其中一个轴为 masonry 布局，另一个轴为普通网格布局。这样，开发人员就能像在 Pinterest 上一样轻松创建画廊风格的布局。更多详情，请参阅 Firefox bug 1607954。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 77 | 是 |
| 开发者版 | 77 | 否 |
| Beta | 77 | 否 |
| 发行版 | 77 | 否 |
| 首选项名称 | `layout.css.grid-template-masonry-value.enabled` |

### fit-content() 函数

`fit-content()` 函数适用于 `width` 和其他大小属性。CSS 网格布局轨迹大小已经支持该函数。（详情请参见 Firefox bug 1312588）

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 91 | 否 |
| 开发者版 | 91 | 否 |
| Beta | 91 | 否 |
| 发行版 | 91 | 否 |
| 首选项名称 | `layout.css.fit-content-function.enabled` |

### 滚动驱动的动画

滚动驱动动画早先被称为“滚动链接动画”，它取决于滚动条的滚动位置，而不是时间或其他维度。通过 `scroll-timeline-name` (en-US) 和 `scroll-timeline-axis` (en-US) 属性（以及 `scroll-timeline` (en-US) 速记属性），你可以指定特定命名容器中的特定滚动条作为滚动驱动动画的源。然后，通过将 `animation-timeline` (en-US) 属性设置为使用 `scroll-timeline-name` 定义的名称值，可以将滚动时间轴与动画关联。

使用 `scroll-timeline` (en-US) 速记属性时，属性值的顺序必须是 `scroll-timeline-name` (en-US) 后跟 `scroll-timeline-axis` (en-US)。完整属性和速记属性均可在首选项后面使用。

也可以使用 `scroll()` (en-US) 函数标记和 `animation-timeline` (en-US) 来表示时间轴将使用祖先元素中的滚动条轴。

有关详细信息，请参阅 Firefox bug 1807685、Firefox bug 1804573、Firefox bug 1809005、Firefox bug 1676791、Firefox bug 1754897 和 Firefox bug 1737918。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 110 | 否 |
| 开发者版 | 110 | 否 |
| Beta | 110 | 否 |
| 发行版 | 110 | 否 |
| 首选项名称 | `layout.css.scroll-driven-animations.enabled` |

### :has() 伪类

`:has()` 伪类会选择包含作为参数传递的选择器的元素。（详见 Firefox bug 1771896）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 103 | 否 |
| 开发者版 | 103 | 否 |
| Beta | 103 | 否 |
| 发行版 | 103 | 否 |
| 首选项名称 | `layout.css.has-selector.enabled` |

### @font-face src 特性检查

`@font-face` `src` 描述符现在支持 `tech()` 函数，允许根据用户代理是否支持特定字体特性或技术来决定是否下载字体资源。详情请参见 Firefox bug 1715546。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 105 | 是 |
| 开发者版 | 105 | 否 |
| Beta | 105 | 否 |
| 发行版 | 105 | 否 |
| 首选项名称 | `layout.css.font-tech.enabled` |

### round() 数学函数

CSS `round()` (en-US) 函数是一个数学函数，可根据选定的舍入策略对数字（或表达式的结果）进行舍入。详情请参见 Firefox bug 1764850。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 108 | 是 |
| 开发者版 | 108 | 否 |
| Beta | 108 | 否 |
| 发行版 | 108 | 否 |
| 首选项名称 | `layout.css.round.enabled` |

### font-variant-emoji

通过 CSS `font-variant-emoji` (en-US) 属性，你可以设置显示表情符号的默认显示样式。详情请参见（Firefox bug 1461589）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 108 | 是 |
| 开发者版 | 108 | 否 |
| Beta | 108 | 否 |
| 发行版 | 108 | 否 |
| 首选项名称 | `layout.css.font-variant-emoji.enabled` |

### page-orientation

**`page-orientation`** CSS `@page` at-rule 的描述符控制打印页面的旋转。当页面方向发生变化时，它将处理跨页面的内容流。该行为与 `size` (en-US) 描述符不同，用户可以定义页面的旋转方向。详情请参见（Firefox bug 1673987）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 111 | 是 |
| 开发者版 | 111 | 否 |
| Beta | 111 | 否 |
| 发行版 | 111 | 否 |
| 首选项名称 | `layout.css.page-orientation.enabled` |

### prefers-reduced-transparency 媒体特性

 CSS `prefers-reduced-transparency`` (en-US) 媒体特性可让你检测用户是否已启用设置，以尽量减少设备上的透明或半透明图层效果。
 更多详情请参见（Firefox bug 1736914）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 113 | 否 |
| 开发者版 | 113 | 否 |
| Beta | 113 | 否 |
| 发行版 | 113 | 否 |
| 首选项名称 | `layout.css.prefers-reduced-transparency.enabled` |

### inverted-colors 媒体特性

通过 CSS `inverted-colors` (en-US) 媒体特性，可以检测用户代理或底层操作系统是否正在反转颜色。详情请参阅（Firefox bug 1794628）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 114 | 否 |
| 开发者版 | 114 | 否 |
| Beta | 114 | 否 |
| 发行版 | 114 | 否 |
| 首选项名称 | `layout.css.inverted-colors.enabled` |

### 具名观看进度时间线属性

通过 CSS `view-timeline-name` (en-US) 属性，你可以为特定元素赋予一个名称，表明其祖先滚动元素是视图进度时间轴的来源。然后，可以将该名称分配给 `animation-timeline`，当相关元素在其祖先滚动器的可见区域内移动时，`animation-timeline` 就会为其制作动画。详情请参见（Firefox bug 1737920）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 114 | 否 |
| 开发者版 | 114 | 否 |
| Beta | 114 | 否 |
| 发行版 | 114 | 否 |
| 首选项名称 | `layout.css.scroll-driven-animations.enabled` |

### 匿名观看进度时间线属性

通过 CSS `view()` (en-US) 函数，可以指定元素的 `animation-timeline` 为视图进度时间轴，当元素在其父元素滚动条的可见区域内移动时，该时间轴将为其制作动画。该函数定义了提供时间轴的父元素的轴，以及动画开始和开始的可见区域的嵌入区。详情请参见（Firefox bug 1808410）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 114 | 否 |
| 开发者版 | 114 | 否 |
| Beta | 114 | 否 |
| 发行版 | 114 | 否 |
| 首选项名称 | `layout.css.scroll-driven-animations.enabled` |

### offset-position 属性

CSS `offset-position` (en-US) 属性定义了元素在路径上的初始位置。该属性的语法中新增了一个名为 `normal` 的关键字。使用该关键字时，元素在 `offset-path` (en-US) 上的初始起始位置取决于用于指定 `offset-path` 属性值的 CSS 函数（`path()` (en-US) 或 `ray()` (en-US)）。更多信息，请参阅 `offset-position` (en-US)。详情请参见（Firefox bug 1559232）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 116 | 是 |
| 开发者版 | 116 | 否 |
| Beta | 116 | 否 |
| 发行版 | 116 | 否 |
| 首选项名称 | `layout.css.motion-path-offset-position.enabled` |

### abs() 和 sign() 数学函数

CSS `abs()` (en-US) 和 `sign()` (en-US) 数学函数允许你分别获取参数的绝对值和符号。详情请参见 Firefox bug 1814588 和 Firefox bug 1814589。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 117 | 是 |
| 开发者版 | 117 | 否 |
| Beta | 117 | 否 |
| 发行版 | 117 | 否 |
| 首选项名称 | `layout.css.abs-sign.enabled` |

### rect() 和 xywh() 基本图形函数

通过 CSS `rect()` (en-US) 和 `xywh()` (en-US) 形状函数，你可以使用 `<basic-shape>` 数据类型定义矩形。在 CSS 属性（如 `offset-path` (en-US)）中，这些函数用于定义元素移动路径的形状。使用 `rect()` 函数，可以指定矩形边缘与包含块的顶部边缘和左侧边缘的偏移量。使用 `xywh()` 函数，可以指定矩形边缘与包含块的左边缘和顶边缘的偏移量，以及矩形的宽度和高度。在这两个函数中，都可以选择对边角进行舍入。有关详细信息，请参阅 `rect()` 函数的 Firefox bug 1786161 和 `xywh()` 函数的 Firefox bug 1786160。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 117 | 是 |
| 开发者版 | 117 | 否 |
| Beta | 117 | 否 |
| 发行版 | 117 | 否 |
| 首选项名称 | `layout.css.motion-path-basic-shapes.enabled`、`layout.css.basic-shape-rect.enabled`、`layout.css.basic-shape-xywh.enabled` |

SVG
---

### SVGPathSeg API 接口

SVGPathSeg API 接口将不再包含，并被置于首选项之后。其中包括 `SVGPathSegList`、SVGPathElement.getPathSegAtLength() (en-US)、`SVGAnimatedPathData`。（详见 Firefox bug 1388931）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 97 | 否 |
| 开发者版 | 97 | 否 |
| Beta | 97 | 否 |
| 发行版 | 97 | 否 |
| 首选项名称 | `dom.svg.pathSeg.enabled` |

JavaScript
----------

### 数组（可迭代）分组方法

`Object.groupBy()` 和 `Map.groupBy()` 静态方法分别用于使用字符串或测试函数返回的值对可迭代元素进行分组。当字符串可用于表示元素组时，应使用第一个方法，而当元素与特定对象相关联时，可使用 `Map` 中的方法。（详见 Firefox bug 1841518）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 117 | 否 |
| 开发者版 | NA | 否 |
| Beta | NA | 否 |
| 发行版 | NA | 否 |
| 首选项名称 | `javascript.options.experimental.array_grouping` |

### 数组转移

`ArrayBuffer.prototype.transfer()` 和 `ArrayBuffer.prototype.transferToFixedLength()` 方法用于从一个`ArrayBuffer` 向另一个 `ArrayBuffer` 转移内存所有权。`transferToFixedLength()`方法总是创建固定长度的缓冲区，而 `transfer()` 方法可以创建可变长度的缓冲区，但前提是原始缓冲区的长度是可变的。传输后，原始缓冲区将从原始内存中分离，因此无法使用；可以使用 `ArrayBuffer.prototype.detached` 检查其状态。（详情请参见 Firefox bug 1841113）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 117 | 否 |
| 开发者版 | NA | 否 |
| Beta | NA | 否 |
| 发行版 | NA | 否 |
|
| 首选项名称 | `javascript.options.experimental.arraybuffer_transfer` |

### 字符串 isWellFormed() 和 toWellFormed() 方法

JavaScript 中的字符串由无符号 16 位整数序列表示，因此有可能出现有效字符串值不是格式良好的 Unicode 文本的情况。`String.prototype.isWellFormed()` 和 `String.prototype.toWellFormed()` 方法分别用于检查字符串是否为格式正确的 Unicode 文本，以及将字符串转换为格式正确的 Unicode 文本。详见 tc39/proposal-is-usv-string 和 Firefox bug 1825005。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 115 | 否 |
| 开发者版 | - | - |
| Beta | - | - |
| 发行版 | - | - |
| 首选项名称 | `javascript.options.experimental.well_formed_unicode_strings` |

API
---

### 图形：Canvas、WebGL 和 WebGPU

#### 热点区域

鼠标坐标是否位于画布上的特定区域内是一个需要解决的常见问题。通过点击区域 API，可以定义画布的某个区域，并为将画布上的交互式内容展示给辅助工具提供了另一种可能性。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 30 | 否 |
| 开发者版 | 30 | 否 |
| Beta | 30 | 否 |
| 发行版 | 30 | 否 |
| 首选项名称 | `canvas.hitregions.enabled` |

#### WebGL：草稿扩展

启用此偏好设置后，当前处于“草稿”状态且正在测试的任何 WebGL 扩展都将启用。目前，Firefox 没有正在测试的 WebGL 扩展。

#### WebGPU API

WebGPU API 为使用用户设备或计算机的图形处理单元（GPU）执行计算和图形渲染提供底层支持。请参见 Firefox bug 1602129，了解我们在此 API 方面的进展。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 113 | 是 |
| 开发者版 | 73 | 否 |
| Beta | 73 | 否 |
| 发行版 | 73 | 否 |
| 首选项名称 | `dom.webgpu.enabled` |

### WebRTC 和媒体

以下试验性特性包括 WebRTC API、网络音频 API、媒体源扩展 API、加密媒体扩展 API (en-US) 和 Media 捕获和流 API。

#### 异步 SourceBuffer 添加和移除

这将为 SourceBuffer 添加基于 promise 的 `appendBufferAsync()` (en-US) 和 `removeAsync()` (en-US) 方法，用于添加和删除媒体源缓冲区。更多信息请参见 Firefox bug 1280613 和 Firefox bug 778617。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 62 | 否 |
| 开发者版 | 62 | 否 |
| Beta | 62 | 否 |
| 发行版 | 62 | 否 |
| 首选项名称 | `media.mediasource.experimental.enabled` |

#### AVIF 严格合规性

`image.avif.compliance_strictness` 偏好设置可用于控制处理 AVIF 图像时应用的*严格程度*。这允许 Firefox 用户显示在某些其他浏览器上呈现的图像，即使这些图像并不严格符合标准。

允许的值为：

* `0`: 接受建议（“应该”）和要求（“必须”）中违反规范的图像，前提是它们可以被安全或明确地解释。
* `1`（默认）：拒绝违反要求，但允许违反建议。
* `2`: 严格。拒绝任何违反要求或建议的行为。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 92 | 1 |
| 开发者版 | 92 | 1 |
| Beta | 92 | 1 |
| 发行版 | 92 | 1 |
| 首选项名称 | `image.avif.compliance_strictness` |

#### JPEG XL 支持

如果启用此特性，Firefox 支持 JPEG XL 图像。详情请参见 Firefox bug 1539075。

请注意，如下表所示，该特性只适用于 Nightly 构建版本（无论是否设置了偏好设置）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 90 | 否 |
| 开发者版 | — | — |
| Beta | — | — |
| 发行版 | — | — |
| 首选项名称 | `image.jxl.enabled` |

#### OpenFont COLRv1 字体

该特性支持 OpenFont COLRv1 字体规范。这样就可以使用 CSS `@font-face` 规则或 CSS 字体加载 API 来加载带有渐变、合成和混合特性的压缩友好型彩色矢量字体。详情请参见 Firefox bug 1740530。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 105 | 否 |
| 开发者版 | 105 | 否 |
| Beta | 105 | 否 |
| 发行版 | 105 | 否 |
| 首选项名称 | `gfx.font_rendering.colr_v1.enabled` |

#### CSS 属性和值 API

CSS 属性和值 API 允许开发人员通过 JavaScript 中的 `registerProperty()` (en-US)或 CSS 中的 `@property` 规则注册自定义 CSS 属性。使用这两种方法注册属性时，可以进行类型检查、设置默认值，以及设置是否从父元素继承值。详情请参见 Firefox bug 1840480。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 116 | 是 |
| 开发者版 | 116 | 否 |
| Beta | 116 | 否 |
| 发行版 | 116 | 否 |
| 首选项名称 | `layout.css.property-and-value-api.enabled` |

#### CSS 自定义高亮 API

CSS 自定义高亮 API 为文档中任意文本范围的样式化提供了一种机制（概括了其他高亮伪元素的行为，如 `::selection`、`::spelling-error`、`::grammar-error` 和 `::target-text`）。这些范围在 JavaScript 中使用 `Range` 实例进行定义，这些实例在 `Highlight` (en-US) 中分组，然后使用 `HighlightRegistry` (en-US) 注册名称。CSS `::highlight` (en-US) 伪元素用于为已注册的高亮应用样式。详情请参见 Firefox bug 1703961。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 117 | 是 |
| 开发者版 | 117 | 否 |
| Beta | 117 | 否 |
| 发行版 | 117 | 否 |
| 首选项名称 | `dom.customHighlightAPI.enabled` |

### Service Worker

#### 在导航时预加载 service worker 资源

`NavigationPreloadManager` (en-US) 接口可用于在导航至页面时启用资源预加载。预加载与 Worker 启动同时进行，从而缩短了从开始导航到获取资源的总时间。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 99 | 是 |
| 开发者版 | 97 | 否 |
| Beta | 97 | 否 |
| 发行版 | 97 | 否 |
| 首选项名称 | `dom.serviceWorkers.navigationPreload.enabled` |

### WebVR API

#### WebVR API（已禁用）

已废弃的 WebVR API 即将被移除。在所有版本中默认禁用该 API。（Firefox bug 1750902）

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 98 | 否 |
| 开发者版 | 98 | 否 |
| Beta | 98 | 否 |
| 发行版 | 98 | 否 |
| 首选项名称 | `dom.vr.enabled` |

### HTML DOM API

#### Popover API

Firefox 现在支持 Popover API (en-US)。

以下 Web API 现在已经得到实现：

* `HTMLButtonElement.popoverTargetElement` (en-US) 和 `HTMLButtonElement.popoverTargetAction` (en-US)。
* `HTMLInputElement.popoverTargetElement` (en-US) 和 `HTMLInputElement.popoverTargetAction` (en-US)。
* `HTMLElement.popover` (en-US)、`HTMLElement.hidePopover()` (en-US)、`HTMLElement. showPopover()` (en-US) 和 `HTMLElement.togglePopover()` (en-US)。
* `HTMLElement` `beforetoggle` 事件 (en-US)、`HTMLElement` `toggle_event` 事件 (en-US) 和 `ToggleEvent` (en-US)。

CSS 更新包括：

* `:popover-open` (en-US)
* `::backdrop` 已经得到扩展以支持 popover。

以下 HTML 全局属性得到了支持：

* `popovertarget`
* `popovertargetaction`

参见 Firefox bug 1823757 以获取更多细节。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 114 | 否 |
| 开发者版 | 114 | 否 |
| Beta | 114 | 否 |
| 发行版 | 114 | 否 |
| 首选项名称 | `dom.element.popover.enabled` |

#### HTMLMediaElement 方法：setSinkId()

`HTMLMediaElement.setSinkId()` (en-US) 允许你在 `HTMLMediaElement` 上设置音频输出设备的 sink ID，从而更改音频的输出位置。详情请参见 Firefox bug 934425。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 64 | 否 |
| 开发者版 | 64 | 否 |
| Beta | 64 | 否 |
| 发行版 | 64 | 否 |
| 首选项名称 | `media.setsinkid.enabled` |

#### HTMLMediaElement 属性：audioTracks 和 videoTracks

启用此特性可为所有 HTML 媒体元素添加 `HTMLMediaElement.audioTracks` 和 `HTMLMediaElement.videoTracks` 属性。不过，由于 Firefox 目前不支持多音频和视频音轨，这些属性的最常见用例不起作用，因此默认情况下它们都被禁用。详情请参见 Firefox bug 1057233。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 33 | 否 |
| 开发者版 | 33 | 否 |
| Beta | 33 | 否 |
| 发行版 | 33 | 否 |
| 首选项名称 | `media.track.enabled` |

#### ClipboardItem

现在支持 `Clipboard API` 的 `ClipboardItem` (en-US) 接口，`Clipboard.write()` 接受`剪贴板项` (en-US)序列，而不是之前实现的`dataTransfer 对象`。它可在首选项前缀 `dom.events.asyncClipboard.clipboardItem`（即之前的 `dom.events.asyncClipboard.dataTransfer`）使用。详情请参见 Firefox bug 1619947。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 87 | 否 |
| 开发者版 | 87 | 否 |
| Beta | 87 | 否 |
| 发行版 | 87 | 否 |
| 首选项名称 | `dom.events.asyncClipboard.clipboardItem` |

#### ClipboardRead

`Clipboard`接口的 Clipboard.read() (en-US) 方法现在也可在 `dom.events.asyncClipboard.read` 首选项设置下使用，而以前则在 `dom.events.asyncClipboard.clipboardItem` 首选项设置下使用。（详情请参见 Firefox bug 1701512）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 90 | 否 |
| 开发者版 | 90 | 否 |
| Beta | 90 | 否 |
| 发行版 | 90 | 否 |
| 首选项名称 | `dom.events.asyncClipboard.read` |

#### HTML 净化 API

`HTML Sanitizer API` (en-US) 允许开发人员获取不受信任的 HTML 字符串，并对其进行净化，以便安全地插入到文档的 DOM 中。目前仍在考虑每个配置属性中的默认元素（需要进行净化的元素）。因此，配置参数尚未实现（请参阅`构造函数` (en-US)获取更多信息）。详情请参见 Firefox bug 1673309。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 84 | 否 |
| 开发者版 | 84 | 否 |
| Beta | 84 | 否 |
| 发行版 | 84 | 否 |
| 首选项名称 | `dom.security.sanitizer.enabled` |

#### GeometryUtils 方法：convertPointFromNode()、convertRectFromNode() 和 convertQuadFromNode()

`GeometryUtils` 方法 `convertPointFromNode()`、`convertRectFromNode()` 和 `convertQuadFromNode()` 将给定的点、矩形或四边形从调用它们的 `Node` 映射到另一个节点。（详见 Firefox bug 918189）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 31 | 是 |
| 开发者版 | 31 | 否 |
| Beta | 31 | 否 |
| 发行版 | 31 | 否 |
| 首选项名称 | `layout.css.convertFromNode.enable` |

#### GeometryUtils 方法：getBoxQuads()

`GeometryUtils` 方法 `getBoxQuads()` 返回 `Node` 相对于任何其他节点或视口的 CSS 框。（详见 Firefox bug 917755）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 31 | 是 |
| 开发者版 | 31 | 否 |
| Beta | 31 | 否 |
| 发行版 | 31 | 否 |
| 首选项名称 | `layout.css.getBoxQuads.enabled` |

#### ElementInternals：表单相关自定义元素方法和属性

新增 `ElementInternals` (en-US) 属性和方法，允许自定义元素与表单交互：

* `form` (en-US) 属性可获取与元素相关联的表单。
* `labels` (en-US) 属性获取与元素关联的标签列表。
* `willValidate` (en-US)属性检查自定义表单元素是否会被验证。
* 如果需要，`setFormValue()` (en-US) 方法会设置净化值和用户输入的数据。

详见 Firefox bug 1556362、Firefox bug 1556373、Firefox bug 1556365、Firefox bug 1556449。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 95 | 是 |
| 开发者版 | 95 | 否 |
| Beta | 95 | 否 |
| 发行版 | 95 | 否 |
| 首选项名称 | `dom.webcomponents.formAssociatedCustomElement.enabled` |

### 付款请求 API

#### 首要付款处理

支付请求应用程序接口支持在网页内容或应用程序中处理基于网络的支付。由于在用户界面测试过程中出现了一个错误，我们决定推迟发布该 API，同时讨论对 API 可能进行的修改。相关工作正在进行中。（详见 Firefox bug 1318984）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 55 | 否 |
| 开发者版 | 55 | 否 |
| Beta | 55 | 否 |
| 发行版 | 55 | 否 |
| 首选项名称 | `dom.payments.request.enabled` and`dom.payments.request.supportedRegions` |

### WebShare API

Web 分享 API (en-US) 允许从网站共享文件、URL 和其他数据。该特性在安卓系统的所有版本中均已启用，但在桌面系统中则需要指定首选项设置（除非另有说明）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 71 | 否 (default). 是 (Windows from version 92) |
| 开发者版 | 71 | 否 |
| Beta | 71 | 否 |
| 发行版 | 71 | 否 (Desktop). 是 (Android). |
| 首选项名称 | `dom.webshare.enabled` |

### 屏幕方向 API

#### ScreenOrientation.lock()

`ScreenOrientation.lock()` (en-US) 方法允许在设备支持和浏览器预锁定要求允许的情况下，将设备锁定为特定方向。通常只有在移动设备上全屏显示文档时才允许锁定方向。详见 Firefox bug 1697647。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 111 | 是 |
| 开发者版 | 97 | 否 |
| Beta | 97 | 否 |
| 发行版 | 97 | 否 |
| 首选项名称 | `dom.screenorientation.allow-lock` |

### 优先级任务调度 API

优先级任务调度 API (en-US) 提供了一种标准化的方法，可对属于应用程序的所有任务进行优先排序，无论这些任务是在网站开发人员的代码中定义的，还是在第三方库和框架中定义的。

Firefox Nightly（仅）从 Firefox 101 开始启用此特性。其他版本没有提供启用该特性的首选项。

### 通知 API

在 Windows 系统和 Nightly 版本中，通知的 `requireInteraction` 属性默认设置为 true（Firefox bug 1794475）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 117 | 是 |
| 开发者版 | 117 | 否 |
| Beta | 117 | 否 |
| 发行版 | 117 | Windows only |
| 首选项名称 | `dom.webnotifications.requireinteraction.enabled` |

安全与隐私
-----

### 在加密页面上阻止纯文本请求

为了帮助减轻由加密页面上的 Flash 内容引起的中间人攻击（MitM），已添加了一个首选项，将 `OBJECT_SUBREQUEST` 视为活动内容。详见 Firefox bug 1190623。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 59 | 否 |
| 开发者版 | 59 | 否 |
| Beta | 59 | 否 |
| 发行版 | 59 | 否 |
| 首选项名称 | `security.mixed_content.block_object_subrequest` |

### “不安全页面”标签

当页面以不安全方式加载（即使用 HTTP 而不是 HTTPS 加载）时，这两个首选项会在地址栏中传统的锁图标旁添加“不安全”文本标签。详见 Firefox bug 1335970。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 60 | 否 |
| 开发者版 | 60 | 否 |
| Beta | 60 | 否 |
| 发行版 | 60 | 否 |
| 首选项名称 | 普通浏览模式下：`security.insecure_connection_text.enabled`，隐私浏览模式下：`security.insecure_connection_text.pbmode.enabled` |

### 升级混合显示内容

启用此首选项设置后，Firefox 会在安全页面上自动将媒体内容请求从 HTTP 升级到 HTTPS。这样做的目的是防止出现混合内容的情况，即某些内容以安全方式加载，而其他内容则不安全。如果升级失败（因为媒体主机不支持 HTTPS），则不会加载媒体。（详见 Firefox bug 1435733）。

这也会更改控制台警告；如果升级成功，消息会显示请求已升级，而不是显示警告。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 84 | 是 |
| 开发者版 | 60 | 否 |
| Beta | 60 | 否 |
| 发行版 | 60 | 否 |
| 首选项名称 | `security.mixed_content.upgrade_display_content` |

### 权限策略 / 特性策略

权限策略 允许网络开发人员有选择地启用、禁用和修改浏览器中某些特性和 API 的行为。它与 CSP 类似，但控制的是特性而不是安全行为。请注意，在 Firefox 中实现的是**特性策略**，这是该规范早期版本中使用的名称。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 65 | 否 |
| 开发者版 | 65 | 否 |
| Beta | 65 | 否 |
| 发行版 | 65 | 否 |
| 首选项名称 | `dom.security.featurePolicy.header.enabled` |

### Clear-Site-Data“cache”指令

`Clear-Site-Data` HTTP 响应标头 `cache` 指令会清除请求网站的浏览器缓存。

**备注：** 这原本在默认情况下是启用的，但在版本 94（Firefox bug 1729291）中被置于首选项之后。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 63 | 否 |
| 开发者版 | 63 | 否 |
| Beta | 63 | 否 |
| 发行版 | 63 | 否 |
| 首选项名称 | `privacy.clearsitedata.cache.enabled` |

HTTP
----

### 默认 SameSite=Lax

`SameSite` cookie 的默认值为 `Lax`。在此设置下，只有当用户导航到原始站点时才会发送 cookie，而不会发送跨站点子请求以将图像或框架加载到第三方站点等。详见 Firefox bug 1617609。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 69 | 否 |
| 开发者版 | 69 | 否 |
| Beta | 69 | 否 |
| 发行版 | 69 | 否 |
| 首选项名称 | `network.cookie.sameSite.laxByDefault` |

### HTTP 状态码 103

服务器可能会发送 `103 Early Hints` HTTP 信息响应状态代码，以允许用户代理在服务器仍在准备完整响应时开始预加载资源。详见 Firefox bug 1813035。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 111 | 是 |
| 开发者版 | 111 | 是 |
| Beta | 111 | 是 |
| 发行版 | 102 | 否 |
| 首选项名称 | `network.early-hints.enabled` 和 `network.early-hints.preconnect.enabled` |

### Access-Control-Allow-Headers 通配符不包含 Authorization 标头

`Access-Control-Allow-Headers` 是 CORS 预检请求的响应标头，表示哪些请求标头可以包含在最终请求中。响应指令可包含通配符（`*`），表示最终请求可包含除 `Authorization` 标头以外的所有标头。

默认情况下，Firefox 在收到带有 `Access-Control-Allow-Headers: *` 的响应时会包含 `Authorization` 标头。将首选项设置为 `false` 可确保 Firefox 不包含 `Authorization` 标头。详见 Firefox bug 1687364。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 115 | 是 |
| 开发者版 | 115 | 是 |
| Beta | 115 | 是 |
| 发行版 | 115 | 是 |
| 首选项名称 | `network.cors_preflight.authorization_covered_by_wildcard` |

开发者工具
-----

Mozilla 的开发者工具在不断发展。我们会尝试新的想法，添加新的特性，并在 Nightly 和开发者版本渠道上进行测试，然后再通过测试版发布。以下是目前开发者工具的实验特性。

### 执行上下文选择器

该特性可在控制台命令行上显示一个按钮，让你更改输入表达式的执行环境。（详见 Firefox bug 1605154 和 Firefox bug 1605153）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 75 | 否 |
| 开发者版 | 75 | 否 |
| Beta | 75 | 否 |
| 发行版 | 75 | 否 |
| 首选项名称 | `devtools.webconsole.input.context` |

### 响应式设计模式中支持移动端手势

鼠标手势用于模拟移动手势，例如轻扫/滚动、双击和缩放，以及长按选择/打开上下文菜单。（详见 Firefox bug 1621781、Firefox bug 1245183 和 Firefox bug 1401304）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 76[1] | 是 |
| 开发者版 | 76[1] | 是 |
| Beta | 76[1] | 是 |
| 发行版 | 76[1] | 否 |
| 首选项名称 | n/a |

[1] Firefox 76 添加了对使用双击手势缩放的支持。其他手势是为 Firefox 79 添加的。

### 网络监视器中显示服务器发送事件

网络监控器会显示服务器发送事件的信息。（详见 Firefox bug 1405706）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 80 | 是 |
| 开发者版 | 80 | 是 |
| Beta | 80 | 否 |
| 发行版 | 80 | 否 |
| 首选项名称 | `devtools.netmonitor.features.serverSentEvents` |

### CSS 浏览器兼容性工具提示栏

CSS 规则视图可以在存在已知问题的 CSS 属性旁边显示浏览器兼容性工具提示。详见检查和编辑 HTML > 浏览器兼容性警告。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 81 | 否 |
| 开发者版 | 81 | 否 |
| Beta | 81 | 否 |
| 发行版 | 81 | 否 |
| 首选项名称 | `devtools.inspector.ruleview.inline-compatibility-warning.enabled` |

用户界面
----

### 桌面缩放

该特性可让你在桌面端实现流畅的捏合缩放，而无需像移动设备那样重新刷新布局。（详见 Firefox bug 1245183 和 Firefox bug 1620055）。

| 更新通道 | 添加的版本 | 默认启用？ |
| --- | --- | --- |
| Nightly | 42 | 是 |
| 开发者版 | 42 | 否 |
| Beta | 42 | 否 |
| 发行版 | 42 | 否 |
| 首选项名称 | `apz.allow_zooming`，Windows 中 `apz.windows.use_direct_manipulation` |

参见
--

* Firefox 开发者发行日志
* Firefox Nightly
* Firefox 开发者版本


与 Firefox 开发者相关的发行说明 - Mozilla

与 Firefox 开发者相关的发行说明
====================

本页提供每个 Firefox 的版本的“与 Firefox 开发者相关的发行说明”文章的链接。这些日志文章可以让你查看每个 Firefox 版本增加了哪些功能和修复的错误。

1. 致 Firefox 3 开发者
2. Firefox 121 的开发者说明
3. Firefox 120 的开发者说明
4. Firefox 119 的开发者说明
5. Firefox 78 的开发者说明
6. Firefox 65 for developers
7. Firefox 59 for developers
8. Firefox 41 for developers
9. Firefox 33 for developers
10. Firefox 32 for developers
11. Firefox 31 for developers
12. Firefox 27 for developers
13. Firefox 26 for developers
14. Firefox 25 for developers
15. Firefox 24 for developers
16. Firefox 22 for developers
17. Firefox 21 for developers
18. Firefox 20 for developers
19. Firefox 19 for developers
20. Firefox 18 for developers
21. Firefox 14 for developers


Firefox 21 for developers - Mozilla

Firefox 21 for developers
=========================

Web 开发者需要注意的变化
--------------

### HTML

* 实现了`<style>`元素上的`scoped`属性。拥有该属性的`<style>`元素可以通过在 Firefox 20 中实现的 CSS 伪类`:scope`选择器选择到.(Firefox bug 508725).
* 实现了新的`<main>`元素 (Firefox bug 820508).
### JavaScript

* E4X,一个古老的 JavaScript 扩展 (ECMA-357),已经被删除。因为一直以来，只有 Gecko 支持它.(Firefox bug 788293).
* parseInt (en-US)不再将以"0"开头的字符串作为 8 进制数字来解析 (Firefox bug 786135).
### CSS

* `-moz-user-select`属性的属性值在设置为 `none` 时和设置为 `-moz-none` 时效果等同于，这样才能让 Gecko 和其他内核 WebKit(Chrome, Safari),Presto (Opera) 以及 Trident(Internet Explorer) 中的表现相同 (Firefox bug 816298).
* On XHTML content, the `auto` value of `-moz-hyphens` incorrectly applied hyphenation rules when the language was not explicitly declared. This is fixed by (Firefox bug 702121).
* CSS 属性`-moz-orient` (en-US)现在支持新的值 `auto`. 当应用到一个`<meter>`元素或者`<progress>`元素上时，`auto` 就等同于 `horizontal`(Firefox bug 835883).
### DOM

* 实现了`window.location`上的 `origin` 属性 (Firefox bug 828261).
* 实现了 `<input type="time">` 对象上的 `valueAsDate` 和 `valueAsNumber` 方法 (Firefox bug 781570).
* 实现了 `<input type="time">` 对象上的 `min` 和 `max` 属性 (Firefox bug 781572).
* Some new keyCodes for volume control are supported (Firefox bug 674739).
* Some new keyCodes for ancient keyboard layout such as AS/400 are now supported on Windows and Linux (Firefox bug 833719).
* Various keyCode values for OEM sepecific keys on Windows are now supported again (Firefox bug 833719).
* 实现了`window.crypto.getRandomValues`函数 (Firefox bug 440046)。
### SVG

* 实现了`paint-order`属性 (Firefox bug 828805).
### 网络

* 更新 CSP 实现到最新的 CSP 规范 1.0(CR):
    + Support for the spec-compliant `Content-Security-Policy` HTTP header (in addition to the experimental `X-Content-Security-Policy`) has been added (Firefox bug 783049). **Note**: the patch for this new header landed in Firefox 21, it is disabled on builds (Firefox bug 842657).
附加组件和 Mozilla 开发者需要注意的变化
------------------------

* FUEL applications cannot use the Livemarks service anymore (Firefox bug 834492). The Livemarks service is deprecated and phased out in favor of the new async interface.
* History API saw numerous deprecated API being removed:
    + Replaced by `mozIAsyncFavicons`:
        - `nsIFaviconService::setFaviconUrlForPage`
        - `nsIFaviconService::setFaviconData`
        - `nsIFaviconService::getFaviconData`
        - `nsIFaviconService::getFaviconForPage`
        - `nsIFaviconService::setAndLoadFaviconForPage`
        - `nsIFaviconService::getFaviconImageForPage`
        - `nsIFaviconService::getFaviconDataAsDataURL`
    + Replaced by `mozIAsyncLivemarks`:
        - `nsILivemarkService::*`
        - `PlacesUtils.itemIsLivemark`
        - `PlacesUtils.nodeIsLivemarkContainer`
        - `PlacesUtils.nodeIsLivemarkItem`
    + Removed only third argument:
        - `PlacesUIUtils.showBookmarkDialog`
    + No more implemented by Places, use `mozIAsyncHistory` instead:
        - `nsIGlobalHistory2::addURI`
        - `nsIGlobalHistory2::isVisited`
        - `nsIGlobalHistory2::setPageTitle`
    + No more needed, use `onDeleteURI` or `onItemRemoved`:
        - `nsINavHistoryObserver::OnBeforeDeleteURI`
        - `nsINavBookmarkObserver::OnBeforeItemRemoved`
    + Never implemented properly:
        - `nsINavHistoryFullVisitResultNode`
    + Deprecated, use `mozIAsyncHistory::updatePlaces` instead:
        - `nsINavHistoryService::AddVisit`
参见
--

* Firefox 21 发行说明
* Firefox 21 网站兼容性
* Firefox 21 附加组件兼容性
### 更早版本

* Firefox 20 for developers
* Firefox 19 for developers
* Firefox 18 for developers
* Firefox 17 for developers (en-US)
* Firefox 16 for developers (en-US)
* Firefox 15 for developers (en-US)
* Firefox 14 for developers
* Firefox 13 for developers (en-US)
* Firefox 12 for developers (en-US)
* Firefox 11 for developers (en-US)
* Firefox 10 for developers (en-US)
* Firefox 9 for developers (en-US)
* Firefox 8 for developers (en-US)
* Firefox 7 for developers (en-US)
* Firefox 6 for developers (en-US)
* Firefox 5 for developers (en-US)
* Firefox 4 for developers (en-US)
* Firefox 3.6 for developers (en-US)
* Firefox 3.5 for developers (en-US)
* Firefox 3 for developers
* Firefox 2 for developers (en-US)
* Firefox 1.5 for developers (en-US)


Firefox 25 for developers - Mozilla

Firefox 25 for developers
=========================

Web 开发者需要注意的变化
--------------

### CSS

* 新增了 `background-attachment` 属性值 `local` (Firefox bug 483446).
* 新增了一个 Mozilla 私有的媒体查询属性：`-moz-os-version`, 目前该属性只支持 Windows (Firefox bug 810399).
* 实现了新的 `-moz-osx-font-smoothing` (en-US) CSS 属性 (Firefox bug 857142)
### HTML

* 实现了 `<iframe>` 元素的 `srcdoc` 属性，可以用 HTML 代码来定义 `<iframe>` 元素的文档内容 (Firefox bug 802895).
* `HTMLCanvasElement.toBlob` 方法，当第二个参数指定为 `"image/jpeg"` 时，会接受第三个参数，用来指定 jpeg 图片质量。(Firefox bug 891884).
### JavaScript

下面都是 ECMAScript 6 (Harmony) 中的新特性！

* 实现了 `Array.of()` 方法 (Firefox bug 866849).
* 实现了 `Number.parseInt()` 和 `Number.parseFloat()` 方法 (Firefox bug 886949).
* 实现了 `Map.prototype.forEach()` 和 `Set.prototype.forEach()` 方法 (Firefox bug 866847)
* 实现了更多的数学函数：`Math.log10()`, `Math.log2()`, `Math.log1p()`, `Math.expm1()`, `Math.cosh()`, `Math.sinh()`, `Math.tanh()`, `Math.acosh()`, `Math.asinh()`, `Math.atanh()`, `Math.hypot()`, `Math.trunc()`, `Math.sign()` 以及 `Math.cbrt()` (Firefox bug 894026).
* 实现了八进制整数字面量写法 (比如`0o777`) 和二进制整数字面量写法 (比如`0b111`) (Firefox bug 717379).
* 实现了 ECMAScript 国际化 API——ECMA 402（Firefox bug 853301）
### DOM

* 在 Windows 上新增了 `KeyboardEvent.key` 属性对几个与 IME 有关的键盘按键的支持 (Firefox bug 865565), 查看 各按键对应的 key 属性列表 了解详情。
* Metrofox 的键盘事件和桌面版实现统一 (Firefox bug 843236).
* 如果使用 preventDefault() 阻止了 keydown 事件的默认行为，则后续的 keypress 事件就不会触发 (en-US) (Firefox bug 501496)
* 实现了 `HTMLIFrameElement` 接口的 `srcDoc` 属性，可以用 HTML 代码来定义 `<iframe>` 元素的文档内容 (Firefox bug 802895).
* 实现了 `HTMLTableElement` 接口的 `createTBody()` 方法，可以用来获取 (创建) 表格的 `<tbody>` 子元素 (Firefox bug 813034).
* `Range.collapse` 方法的 `toStart` 参数变为可选，且默认值为 `false` (Firefox bug 891340).
* 按照最新 DOM 规范，`window.Future()` 改名为 `window.Promise()`(Firefox bug 884279).
* 实现了 document.firstElementChild, document.lastElementChild, document.children, document.childElementCount 以及 DocumentFragment 的 `parentNode` 等属性 (Firefox bug 895974).
* `navigator.geolocation` 属性更新以符合最新规范。它永远不会返回 `null`。当 `geo.enabled` 偏好设置为 `false` 时，它会返回 `undefined` (Firefox bug 884921).
* `ImageData` API 在 `Worker` 内也可用 (Firefox bug 845545).
### MathML

### SVG

参见
--

* Firefox 25 网站兼容性
### 更早版本

* Firefox 24 for developers
* Firefox 23 for developers (en-US)
* Firefox 22 for developers
* Firefox 21 for developers
* Firefox 20 for developers
* Firefox 19 for developers
* Firefox 18 for developers
* Firefox 17 for developers (en-US)
* Firefox 16 for developers (en-US)
* Firefox 15 for developers (en-US)
* Firefox 14 for developers
* Firefox 13 for developers (en-US)
* Firefox 12 for developers (en-US)
* Firefox 11 for developers (en-US)
* Firefox 10 for developers (en-US)
* Firefox 9 for developers (en-US)
* Firefox 8 for developers (en-US)
* Firefox 7 for developers (en-US)
* Firefox 6 for developers (en-US)
* Firefox 5 for developers (en-US)
* Firefox 4 for developers (en-US)
* Firefox 3.6 for developers (en-US)
* Firefox 3.5 for developers (en-US)
* Firefox 3 for developers
* Firefox 2 for developers (en-US)
* Firefox 1.5 for developers (en-US)


Firefox 14 for developers - Mozilla

Firefox 14 for developers
=========================

Firefox 14 shipped on July 17, 2012. This article lists key changes that are useful for not only Web developers to know about, but also Firefox and Gecko developers as well as add-on developers.

Changes for Web developers
--------------------------

### HTML

* `<progress>`元素不在错误的归为一个表单元素，因此不再有一个`form`属性。
* The default modifier keys for the `accesskey` of HTML contents on Mac are changed to Control+Option. This is the same as WebKit-based browsers on Mac.
### DOM

* input events are fired also on editing host element of contenteditable editor and root element of designMode editor.
* `DOMException.code`已被废弃，根据最新的 DOM Level 4 规范。
* `Range.insertNode()` method now works correctly when used on collapsed ranges.
* The `MozBlobBuilder` interface has been deprecated in favor of the constructor on `Blob`. If you use `MozBlobBuilder` you'll see a warning message in the Web Console.
* The `Blob()` constructor is now available to workers (Firefox bug 736686).
* Support for the Mutation Observers has been landed. It is designed as a replacement for the Mutation Events in DOM3, which has a number of issues regarding performance.
* The `HTMLImageElement` interface's `x` and `y` properties were removed in Gecko 7.0 but restored in this release for compatibility reasons.
* `Document`上的方法`execCommandShowHelp()`和`queryCommandText()`,没有任何作用，已被删除。
* The `GeoPositionAddress` interface, an obsolete part of the Geolocation API, has been removed.
* `localStorage/sessionStorage` now correctly return `undefined` instead of `null` for undeclared keys through property access.
* The `ImageData` object has been implemented (Firefox bug 550309).
* Attributes and methods related to child nodes on `Attr` interface where obsoleted (Firefox bug 737122).
### CSS

* The `text-transform` and `font-variant` CSS properties have been fixed to correctly handle the `i` → `İ` and `ı` → `I` Turkic-specific case pairs.
* The Dutch IJ digraph is now correctly handled by `text-transform: capitalization`. Similarly the Greek letter `Σ`, which has two lowercase forms, `σ` and `ς`, is now correctly handled by `text-transform: lowercase`.
* Support for the `skew()` function has been removed from `transform` property, as it has been removed from the draft standard.
* The syntax for `border-image` has been updated to match the latest revision of the specification; it no longer accepts a trailing slash ("/").
### JavaScript

*No change.*

### MathML

* The syntax of the `statusline` action type on `<maction>` elements has been adjusted to follow the MathML specification.
### HTTP

* Gecko 开始支持新的HTTP `308 永久重定向` 状态码。由于 Gecko 并不区分永久重定向和临时重定向，所以该状态码的表现行为和`307 临时重定向`状态码是一样的，和 302 以及 301 状态码的区别是，它们禁止用户代理改变重定之后的 HTTP 方法 (`POST` 还是 `POST`, `GET` 还是 `GET`).
Changes for Mozilla and add-on developers
-----------------------------------------

### JavaScript 代码模块

#### source-editor.jsm

* Added a keyboard shortcut to toggle commenting for the current selection (Ctrl-/ or Cmd-/ on Mac OS X).
* Added the Ctrl-[ and Ctrl-] keyboard shortcuts for moving the text input position to the beginning and end of the current block.
* Added the new `getLineStart()` and `getLineEnd()` methods.
### XUL

* 在 `<window>` 元素上添加了新的 `fullscreenbutton` 属性；将该属性设置为`true`，会在窗口上添加一个进入全屏模式的按钮。
### 接口

* `nsILocalFile`接口被合并到`nsIFile`接口中。(bug 682360).
* The methods in `nsIPlacesImportExportService` for importing bookmarks have all been removed in favor of the `BookmarkHTMLUtils.jsm` JavaScript code module.
* `nsIDOMGeoPositionAddress` 接口已被移除。
### 拼写检查

* Dictionary names are now parsed as full BCP 47 language tags (bug 730209, bug 741842). Developers are encouraged to not hard-code the name of their language in their dictionary names.
参见
--

* Firefox 13 for developers (en-US)
* Firefox 12 for developers (en-US)
* Firefox 11 for developers (en-US)
* Firefox 10 for developers (en-US)
* Firefox 9 for developers (en-US)
* Firefox 8 for developers (en-US)
* Firefox 7 for developers (en-US)
* Firefox 6 for developers (en-US)
* Firefox 5 for developers (en-US)
* Firefox 4 for developers (en-US)
* Firefox 3.6 for developers (en-US)
* Firefox 3.5 for developers (en-US)
* Firefox 3 for developers
* Firefox 2 for developers (en-US)
* Firefox 1.5 for developers (en-US)


Firefox 31 for developers - Mozilla

Firefox 31 for developers
=========================

Web 开发者需要关注的变化

### Developer Tools

*No change.*

### CSS

* CSS 变量的语法从旧的 "var-" 前缀更新为新的 "--" 前缀。（Firefox bug 985838）
* Unwanted white space for multiple of 10,000 in Korean counte.(Firefox bug 985186)
### HTML

*No change.*

### JavaScript

实现了如下 ECMAScript 6 新特性：

* `Array` 方法：`Array.prototype.fill()` (Firefox bug 911147)
* `Math` 函数：`Math.clz32()` (Firefox bug 925123)
* `String` 方法：`String.prototype.normalize()` (Firefox bug 918987).
### Interfaces/APIs/DOM

* Constructor of `KeyboardEvent` has been implemented (Firefox bug 930893).
* `KeyboardEvent.initKeyboardEvent()` has been implemented (Firefox bug 930893).
* `KeyboardEvent.isComposing` attribute has been implemented (Firefox bug 993234).
* `InputEvent` interface has been implemented (Firefox bug 993253).
* `InputEvent.isComposing` attribute has been implemented (Firefox bug 993253).
### MathML

*No change.*

### SVG

*No change.*

### Audio/Video

*No change.*

Security
--------

*No change.*

Changes for add-on and Mozilla developers
-----------------------------------------

*No change.*

See also
--------

* Site Compatibility for Firefox 31
### Older versions

* Firefox 30 for developers (en-US)
* Firefox 29 for developers (en-US)
* Firefox 28 for developers (en-US)
* Firefox 27 for developers
* Firefox 26 for developers
* Firefox 25 for developers
* Firefox 24 for developers
* Firefox 23 for developers (en-US)
* Firefox 22 for developers
* Firefox 21 for developers
* Firefox 20 for developers
* Firefox 19 for developers
* Firefox 18 for developers
* Firefox 17 for developers (en-US)
* Firefox 16 for developers (en-US)
* Firefox 15 for developers (en-US)
* Firefox 14 for developers
* Firefox 13 for developers (en-US)
* Firefox 12 for developers (en-US)
* Firefox 11 for developers (en-US)
* Firefox 10 for developers (en-US)
* Firefox 9 for developers (en-US)
* Firefox 8 for developers (en-US)
* Firefox 7 for developers (en-US)
* Firefox 6 for developers (en-US)
* Firefox 5 for developers (en-US)
* Firefox 4 for developers (en-US)
* Firefox 3.6 for developers (en-US)
* Firefox 3.5 for developers (en-US)
* Firefox 3 for developers
* Firefox 2 for developers (en-US)
* Firefox 1.5 for developers (en-US)


Firefox 18 for developers - Mozilla

Firefox 18 for developers
=========================

Firefox 18 已于 2013 年 1 月 8 日发布。

WEB 开发者需要注意的变化
--------------

### HTML

* 实现了`<ol>`元素上的`reversed`属性 (Firefox bug 601912).
* 实现了`<link>`元素上的`crossorigin`属性 (Firefox bug 786564).
### CSS

* `min-width` 和 `min-height` 属性使用 `auto` 关键字作为初始值 (This has an effect only on flex items as it resolves to `0`, the previous initial value, for other items). (Firefox bug 763689)
* The cascade has been updated: now author `!important` rules override CSS animations (en-US). (Firefox bug 783714)
* `background`简写属性可以包含 CSS3 中的`background-size`属性了。(Firefox bug 570326)
* 初步实现了 Flexbox.默认禁用状态，可以通过设置`layout.css.flexbox.enabled`选项激活该特性.(Firefox bug 666041)
### DOM

* 实现了 `navigator.mozPay` 属性（Firefox bug 767818）
* 实现了 `window.devicePixelRatio` 属性。（Firefox bug 564815）
* 在 MacOS 上实现了`window.navigator.battery` 属性。（Firefox bug 696045）
* 删除了 `MozBlobBuilder`。开发者应该使用 `Blob` 构造函数来创建 `Blob` 对象。（Firefox bug 744907）
* `visibilitychange`事件和页面可见性 API (en-US)取消前缀Firefox bug 812086).
* 实现了 `TextDecoder` 和 `TextEncoder`。（Firefox bug 764234）
* `HTMLMediaElement.src` 被分成了两个属性：一个是标准的 `src` 属性，返回普通的字符串 `DOMString`,另一个是带前缀的`mozSrcObject`属性，返回 media streams (en-US)（Firefox bug 792665）。
### JavaScript

* 实现了 EcmaScript 6 中的直接代理(Firefox bug 703537).警告：该实现包含了一些已知的 bug，以及未根据最新规范草案实现某些特性。不要在生产环境中使用它。
* 实现了 ECMAScript 6 中的字符串方法`contains()`.
### WebGL

### SVG

### MathML

### XUL

### 网络

* HTTP 请求头`Accept-Language` 可以使用两位数字的质量因子（"q-values"）（Firefox bug 672448）。
* HTTP 响应头支持了`X-FRAME-OPTIONS` (en-US)中的`ALLOW-FROM`语法 (Firefox bug 690168).
### 开发者工具

附加组件和 Mozilla 开发者需要注意的变化
------------------------

### 接口变更

`nsIStreamListener`

`onDataAvailable()`方法的第四个参数 (aOffset) 类型改为无符号长整型。(Firefox bug 784912)

`nsIUploadChannel`

`setUploadStream()` 支持了超过 2GB 大小的 content-length (Firefox bug 790617)

`nsIEditor`

删除了 `addEditorObserver()`，使用 `setEditorObserver()` 来替代，`removeEditorObserver()` 不再需要一个 `nsIEditorObserver` 参数（Firefox bug 785091）

`nsIHttpProtocolHandler`

`http-on-modify-request` observers are no longer guaranteed to be called synchronously during
 `nsIChannel.asyncOpen()`. For observers that need to be called during `asyncOpen`(), the new `http-on-opening-request` observer topic has been added. (Firefox bug 800799)

#### 新增接口

#### 移除接口

下面的接口已经被移除。

* `nsIEditorObserver`
参见
--

* Firefox 18 发行说明
* Aurora 18: HiDPI & Touch Events (Mozilla Hacks)
* Firefox 18 网站兼容性
* Firefox 18 附加组件兼容性
### 更早版本

* Firefox 17 for developers (en-US)
* Firefox 16 for developers (en-US)
* Firefox 15 for developers (en-US)
* Firefox 14 for developers
* Firefox 13 for developers (en-US)
* Firefox 12 for developers (en-US)
* Firefox 11 for developers (en-US)
* Firefox 10 for developers (en-US)
* Firefox 9 for developers (en-US)
* Firefox 8 for developers (en-US)
* Firefox 7 for developers (en-US)
* Firefox 6 for developers (en-US)
* Firefox 5 for developers (en-US)
* Firefox 4 for developers (en-US)
* Firefox 3.6 for developers (en-US)
* Firefox 3.5 for developers (en-US)
* Firefox 3 for developers
* Firefox 2 for developers (en-US)
* Firefox 1.5 for developers (en-US)


Firefox 121 的开发者说明 - Mozilla

Firefox 121 的开发者说明
==================

本文提供了有关 Firefox 121 中影响开发者的变更信息。Firefox 121 于 2023 年 12 月 19 日发布。

为 Web 开发者带来的变化
--------------

### HTML

* `<iframe>` 现已支持懒加载，这允许开发者提示特定的 `<iframe>` 仅在可见时才进行加载。这可以减少页面加载时需要获取的资源（某些 `<iframe>` 可能根本不需要获取）以加快初始加载的时间。提示可以通过 `<iframe>` 元素上的 `loading` 属性或 JavaScript 中的 `HTMLIFrameElement.loading` (en-US) 属性提供。（Firefox bug 1622090）。
### CSS

* 已更新 `text-wrap` (en-US) 属性，添加了对 `balance` 和 `stable` 值的支持。`balance` 值用于短的内容块（例如标题），它将确保内容在多行上分布时平衡且易于阅读。`stable` 值确保可编辑的内容在用户编辑时不会被重排（Firefox bug 1731541）。
* 现已支持 `:has()` 选择器（通常被称为*父选择器*）。它允许开发者根据相关联的元素为某个元素应用样式，例如，`li:has(ul)` 将匹配包含子列表的列表，`h1:has(+ p)` 将匹配后面紧跟段落的标题。
* 现已支持 `text-indent` CSS 属性的 `each-line` 和 `hanging` 属性值（Firefox bug 784648），以允许开发者更轻松地指定某些文本缩进样式。此外，开发者现在可以结合多个 `text-indent` 属性值以产生更多创意，例如 `text-indent: 3em hanging each-line`。
### JavaScript

* 现已支持 `Promise.withResolvers()` 静态方法。该方法将 `resolve` 和 `reject` 回调函数暴露在与返回的 `Promise` 相同的作用域中，允许在其构造之后定义兑现或拒绝该 promise 的代码（Firefox bug 1845586）。
* `Date.parse()` 现在接受几种额外的日期格式：
    + 年份大于 9999 的 `YYYY-MMM-DD` 格式（例如 `19999-Jan-01`）（Firefox bug 1858851）
    + `MMM-DD-YYYY` 格式（例如 `Jan-01-1970`）（Firefox bug 1863489）
    + 非 ISO 日期格式的毫秒值（例如 `Jan 1 1970 10:00:00.050`）（Firefox bug 1863125）
    + 现在会忽略格式开头的星期，例如：
        - `Wed, 1970-01-01`
        - `Wed, 1970-Jan-01`星期不需要是正确的，或者根本不是星期几；例如，`foo 1970-01-01` 也是有效的（Firefox bug 1617562）。
* 其他 `Date.parse()` 的修复：
    + `YYYY-M-DD` 和 `YYYY-MM-D` 不再被假定为 GMT，就像 ISO 日期 `YYYY-MM-DD` 一样（Firefox bug 1783731）。
    + 所有格式的毫秒值都被截断为 3 位数，而不是进行四舍五入（Firefox bug 746529）。
### API

* 现已支持 `WebTransportSendStream` (en-US) 接口的 `sendOrder` (en-US) 属性，其允许在创建流之后读取和更改传出的 WebTransport API (en-US) 的*双向*流的相对优先级。请注意，这不能用于修改单向流的优先级，因为 Firefox 将其实现为 `WritableStream` 而不是 `WebTransportSendStream` (en-US)。（有关更多信息，请参阅 Firefox bug 1853444。）
### WebAssembly

* WebAssembly 现已支持尾调用优化，使用新的 `return_call` 和 `return_call_indirect` 替代 `call` (en-US) 指令。这提高了性能，减少了堆栈空间的使用，并增强了与使用尾调用的编程语言的兼容性。（Firefox bug 1858855）。
### WebDriver 一致性（WebDriver BiDi、Marionette）

#### WebDriver BiDi

* 添加了 `browsingContext.contextDestroyed` 事件，该事件在丢弃浏览上下文时触发（Firefox bug 1694390）。
* 添加了对 `script.callFunction` 和 `script.evaluate` 命令的 `userActivation` 参数的支持，该参数允许在模拟用户操作时执行 JavaScript。（Firefox bug 1845488）。
* 添加了对 `browsingContext.userPromptOpened` 事件的 `defaultValue` 字段的支持，该字段允许用户检索提示的默认值（Firefox bug 1851761）。
* 将 `browsingContext.captureScreenshot` 命令的 `viewportOptions` 参数重命名为 `boxOptions`（Firefox bug 1859258）。
* 移除了 `browsingContext.captureScreenshot` 命令的 `scrollIntoView` 参数，其已被下面的 `origin` 参数取代（Firefox bug 1862649）。
* 添加了对 `browsingContext.captureScreenshot` 命令的 `origin` 参数的支持，该参数允许定义屏幕截图的原点和边界。接受的值为 `"document"` 和 `"viewport"`（Firefox bug 1840999）。
* 在序列化 `Window` 对象时，序列化后的值现包含 `context` 属性，该属性被设置为 `Window` 对象的上下文 id，该 id 也可以与 Marionette 交换以引用特定的窗口和框架（Firefox bug 1841049）。
* 修复了嵌套在数据结构（数组、映射等）中的节点（Node）的序列化失败的错误（Firefox bug 1861000）。
* 修复了 `browsingContext.navigate` 命令会返回不正确的导航 id 的错误（Firefox bug 1861655）。

#### Marionette

* 添加了对 `Window` 和 `Frame` 对象的序列化和反序列化的支持（Firefox bug 1274251）。
实验性 Web 特性
----------

以下特性是在 Firefox 121 中新推出的，但默认情况下处于禁用状态。要尝试这些特性，请在 `about:config` 页面上搜索相应的首选项并将其设置为 `true`。你可以在实验性特性页面上找到更多此类特性。

自定义元素状态伪类：`dom.element.customstateset.enabled`

自定义元素可以通过 `states` (en-US) 属性将其内部状态暴露为 `CustomStateSet` (en-US)。CSS 自定义状态伪类（例如 `:--somestate`）可以匹配该元素的状态。（Firefox bug 1861466）

HTML select 元素的 `showPicker()` 方法：`dom.select.showPicker.enabled`

`HTMLSelectElement.showPicker()` (en-US) 方法以编程方式运行浏览器用于 `<select>` 元素的选择器，该方法需要由用户交互触发。（Firefox bug 1854112）

为附加组件开发者带来的变化
-------------

* 修复了当 manifest.json 的 `background` 键包含 `service_worker` 和 `scripts` 声明时会导致后台页面无法启动的错误（Firefox bug 1860304）。

**备注：** 顺便说一下，Chrome 121 中的更改会导致在指定了 `service_worker` 属性时忽略 `scripts` 属性。以前，Chrome 拒绝加载同时包含这两个属性的扩展（Chromium bug 1418934）。有关更多信息，请参阅清单 `background` 键的浏览器支持。
更早期的版本
------

* Firefox 120 for developers
* Firefox 119 for developers
* Firefox 118 for developers (en-US)
* Firefox 117 for developers (en-US)
* Firefox 116 for developers (en-US)
* Firefox 115 for developers (en-US)
* Firefox 114 for developers (en-US)
* Firefox 113 for developers (en-US)
* Firefox 112 for developers (en-US)
* Firefox 111 for developers (en-US)
* Firefox 110 for developers (en-US)
* Firefox 109 for developers (en-US)
* Firefox 108 for developers (en-US)
* Firefox 107 for developers (en-US)
* Firefox 106 for developers (en-US)
* Firefox 105 for developers (en-US)
* Firefox 104 for developers (en-US)
* Firefox 103 for developers (en-US)
* Firefox 102 for developers (en-US)
* Firefox 101 for developers (en-US)
* Firefox 100 for developers (en-US)
* Firefox 99 for developers (en-US)
* Firefox 98 for developers (en-US)
* Firefox 97 for developers (en-US)
* Firefox 96 for developers (en-US)
* Firefox 95 for developers (en-US)
* Firefox 94 for developers (en-US)
* Firefox 93 for developers (en-US)
* Firefox 92 for developers (en-US)
* Firefox 91 for developers (en-US)
* Firefox 90 for developers (en-US)


Firefox 120 的开发者说明 - Mozilla

Firefox 120 的开发者说明
==================

本文提供了有关 Firefox 120 中影响开发者的变更信息。Firefox 120 于 2023 年 11 月 21 日发布。

为 Web 开发者带来的变化
--------------

### HTML

* 对 `media` 属性的支持被重新引入到 `<source>` 元素，并扩展到包括 `<audio>` 和 `<video>` 元素。该属性最初是在 Firefox 15 中添加的，但在 Firefox 53 中被删除，当时它的使用仅限于 `<picture>` 的 `<source>` 子元素。随着这个版本的发布，`media` 属性将在 `<audio>`、`<video>` 和 `<picture>` 的 `<source>` 子元素上可用（Firefox bug 1836128）。
### CSS

* 现已支持 `light-dark()` (en-US) CSS 颜色值函数。这允许在不需要 `prefers-color-scheme` 媒体特性的情况下设置浅色和深色的颜色（Firefox bug 1856999）。
* 现已支持 `lh` 和 `rlh`行距单位。这允许设置相对于元素的行距属性，例如，将背景装饰与多行文本精确对齐（Firefox bug 1310170）。

#### 移除

* 现已移除非标准的 `-moz-image-rect()` CSS 函数，其用于裁剪背景图像。该函数最初是在 Firefox 4 中引入的，但从未被标准化或在其他浏览器中实现（Firefox bug 1853867）。
### JavaScript

* `Date.parse()` 现在接受几种额外的日期格式：
    + 现在接受不符合正式 ISO 标准的数字连接号日期格式（Firefox bug 1557650），包括：
        - `"01-12-1999"`（首个为月份）
        - `"1999-1-5"`（单个数字表示的月份或日期）
        - `"10000-01-12"`（年份超过 9999）
        - `"99-01-05"` 或 `"01-05-99"`（2 位数年份，如果首个为年份，则年份必须大于 31）
        - `"1999-01-05 10:00:00"`（日期和时间之间有空格）。这些日期将使用其他非 ISO 日期格式的典型行为进行解析，例如本地时区和月份转期（4 月 31 日转期到 5 月 1 日，因为 4 月 31 日不存在）。
    + 放宽了直接跟在数字后面的字符的要求，以接受新的格式（Firefox bug 449921），包括：
        - `"DDMonYYYY"`
        - `"Mon.DD.YYYY"`
        - `"DD.Mon.YYYY"`
        - `"YYYY.MM.DD"`
        - `"Mon DD YYYY hh:mmXm"`（`am`/`pm` 直接跟在时间后面）
    + 现已接受将时区 `'Z'` 用于非 ISO 格式（例如 `Jan 1 1970 10:00Z`）（Firefox bug 1852422）
### SVG

无明显变化

### HTTP

* 已启用 `103 Early Hints` HTTP 信息响应状态码，以便预连接到特定的源（页面可能需要来自该源的资源）。有关更详细的信息，请参阅 Firefox bug 1858712。
* Firefox 支持 Global Privacy Control `Sec-GPC` (en-US) 请求标头，该请求标头可用于指示用户不同意网站或服务将其个人信息出售或与第三方共享。用户可以通过将首选项 `privacy.globalprivacycontrol.enabled` 设置为 `true`（在 `about:config` 中）以在正常浏览和隐私浏览模式下启用该标头。`Navigator.globalPrivacyControl` (en-US) 和 `WorkerNavigator.globalPrivacyControl` (en-US) 属性允许 JavaScript 检查用户同意首选项（Firefox bug 1856029）。
### 安全

无明显变化

### API

* 现已支持 `PublicKeyCredential` (en-US) 接口的 `authenticatorAttachment` (en-US) 属性。这允许 Web 应用程序的客户端和服务器代码根据认证器是设备的一部分还是可以在设备之间漫游来配置自身（参见 Firefox bug 1810851）。
* 已支持 Web Authentication API 的最短 PIN 码长度扩展（`minPinLength`） (en-US)，这允许依赖方服务器在创建/注册期间请求认证器的最短 PIN 码长度（Firefox bug 1844450）。
* 现已支持 `Navigator.userActivation` (en-US) 属性和 `UserActivation` (en-US) 接口。它们可用于检查用户是否正在与页面交互，或者自页面加载以来是否已与其进行交互（参见 Firefox bug 1791079）。
### WebDriver 一致性（WebDriver BiDi、Marionette）

#### WebDriver BiDi

* 添加了对 `Proxy` 和 `Generator` 对象的序列化支持（Firefox bug 1841786）。
* 为 `responseStarted` 和 `responseCompleted` 网络事件添加 `authChallenges` 属性（标头中存在的认证挑战列表），这将有助于处理即将到来的 `network.authRequired` 事件（Firefox bug 1855149）。
为附加组件开发者带来的变化
-------------

无明显变化

更早期的版本
------

* Firefox 119 for developers
* Firefox 118 for developers (en-US)
* Firefox 117 for developers (en-US)
* Firefox 116 for developers (en-US)
* Firefox 115 for developers (en-US)
* Firefox 114 for developers (en-US)
* Firefox 113 for developers (en-US)
* Firefox 112 for developers (en-US)
* Firefox 111 for developers (en-US)
* Firefox 110 for developers (en-US)
* Firefox 109 for developers (en-US)
* Firefox 108 for developers (en-US)
* Firefox 107 for developers (en-US)
* Firefox 106 for developers (en-US)
* Firefox 105 for developers (en-US)
* Firefox 104 for developers (en-US)
* Firefox 103 for developers (en-US)
* Firefox 102 for developers (en-US)
* Firefox 101 for developers (en-US)
* Firefox 100 for developers (en-US)
* Firefox 99 for developers (en-US)
* Firefox 98 for developers (en-US)
* Firefox 97 for developers (en-US)
* Firefox 96 for developers (en-US)
* Firefox 95 for developers (en-US)
* Firefox 94 for developers (en-US)
* Firefox 93 for developers (en-US)
* Firefox 92 for developers (en-US)
* Firefox 91 for developers (en-US)
* Firefox 90 for developers (en-US)
* Firefox 89 for developers (en-US)


Firefox 19 for developers - Mozilla

Firefox 19 for developers
=========================

Firefox 19 已于 2013 年 2 月 19 日正式发布。

Web 开发者需要注意的变化
--------------

### JavaScript

* `Map` (en-US) 和 `Set` 对象的 `size()` 方法变成了 `size` 属性。(Firefox bug 807001)
* `Map` (en-US) 和 `Set` 对象新增了一个 clear() 方法。(Firefox bug 805003)
### CSS

* 支持了几个 viewport-relative 的 `<length>` 单位：`vh`, `vw`, `vmin` 以及 `vmax` (Firefox bug 503720)
* CSS Flexbox 脱前缀，但仍然被默认禁止 (Firefox bug 801098).
* `-moz-initial` 脱前缀 (Firefox bug 806068).不过 `-moz-initial` 仍然会作为别名保留一段时间，但仍然推荐你尽快改用 `initial`.
* `text-transform` 属性现在支持了 `full-width` 关键字，which allows a more seamless inclusion of Latin characters in text using ideographic fixed-width characters, like Chinese or Japanese (Firefox bug 774560).
* 实现了 `page-break-inside` (en-US) (Firefox bug 685012).
* `calc()` 函数可以使用在 `<color-stop>` 上 ( `<gradient>`上的一个值).
* 实现了 `@page` @规则 (Firefox bug 115199).但是 `:first`, `:right`, `:left` 仍没实现。
* `:-moz-placeholder` (en-US) 伪类替换成 `::-moz-placeholder` (en-US) 伪元素 (Firefox bug 737786).
### DOM

* `element.getElementsByTagName` 方法开始返回 `HTMLCollection` 对象，而不是以前的 `NodeList` 对象。(Firefox bug 799464).
* 实现了 `File` 对象的 `mozLastModifiedDate` 属性。(Firefox bug 793955)
* 当 `File` 对象的最后修改时间无法获取到时，它的 lastModifiedDate 属性会返回当前日期。(Firefox bug 793459
* 实现了 `CanvasRenderingContext2D`对象的 `isPointInStroke` 方法。(Firefox bug 803124).
* 实现了 `HTMLCanvasElement` 对象的 `toBlob` 方法 (Firefox bug 648610).
* `Node.isSupported` 和 `document.implementation.hasFeature()` 方法会总是放回 `true` (Firefox bug 801425).
* 当调用 `document.createElement(null)` 时，`null` 会被转换成字符串，就像执行了 `document.createElement("null")`。
### XForms

**删除**了对XForms的支持。

附加组件和 Mozilla 开发者需要注意的变化
------------------------

**备注：** A key change in Firefox 19 is that `nsresult` is now strongly typed. This will help make it easier to detect bugs that are caused by mishandling of return values, but may cause existing code to break if it's making incorrect assumptions in this regard.

* `getBrowserSelection()` now returns the selected text in a text input field. As a result, `gContextMenu.isTextSelected` will be `true` when the user selects text in a text input field that is not a password field. (Firefox bug 565717)
* Dict.jsm: `Dict()` now takes a JSON String. `Dict.toJSON()` was added, and it returns a JSON String. (Firefox bug 727967)
### 接口变化

`nsIImgLoadingContent`

The parameter (aObserver) of `addObserver()` method changes from `imgIDecoderObserver` to `imgINotificationObserver`. The `notify()` method of `imgINotificationObserver` is not scriptable, so you need to use `createScriptedObserver()` from `imgITools`.

`nsIChannel`

`contentLength` 属性的类型由 `long` 改成 `int64_t`.

参见
--

* Firefox 19 发行说明
* Firefox 19 网站兼容性
* Firefox 19 附加组件兼容性
### 更早版本

* Firefox 18 for developers
* Firefox 17 for developers (en-US)
* Firefox 16 for developers (en-US)
* Firefox 15 for developers (en-US)
* Firefox 14 for developers
* Firefox 13 for developers (en-US)
* Firefox 12 for developers (en-US)
* Firefox 11 for developers (en-US)
* Firefox 10 for developers (en-US)
* Firefox 9 for developers (en-US)
* Firefox 8 for developers (en-US)
* Firefox 7 for developers (en-US)
* Firefox 6 for developers (en-US)
* Firefox 5 for developers (en-US)
* Firefox 4 for developers (en-US)
* Firefox 3.6 for developers (en-US)
* Firefox 3.5 for developers (en-US)
* Firefox 3 for developers
* Firefox 2 for developers (en-US)
* Firefox 1.5 for developers (en-US)


Firefox 20 for developers - Mozilla

Firefox 20 for developers
=========================

Firefox 20 正式版发布于 2013 年 4 月 2 日。

Web 开发者需要注意的变化
--------------

### HTML

* 实现了`<a>`和`<area>`元素上的`download`属性 (Firefox bug 676619).
* 全局属性 (en-US) `dir` (en-US) 的值开始支持 `auto` (Firefox bug 548206).
### JavaScript

* 实现了`Weakmap.prototype.clear()`方法 (Firefox bug 814562).
* 实现了`Math.imul()`方法，可以进行 C 风格的 32 位整数乘法运算。还不属于 harmony (EcmaScript 6) 提案，所以是非标准的 (Firefox bug 808148).
* Web apps using draggable text with Kinetic 3.x are working, even when using the Cairo canvas backend. (Firefox bug 835064)
* E4X 规范中的for each...in语句被废弃，请使用 ES6 中的for...of语句代替 (Firefox bug 804834).
### CSS

* CSS Flexbox (en-US)默认开启，不需要设置 about:config.
* 实现了 CSS Masking specification 中的 `mask-type` 属性（Firefox bug 793617）。
### DOM

* `HTMLMediaElement`支持可`playbackRate`属性 (both read and write), with pitch correction. Pitch correction can be controlled using the property `mozPreservesPitch` (Firefox bug 495040).
* CSSOM: 实现了新的`CSSGroupingRule`和`CSSConditionRule` (Firefox bug 814907).
* CSSOM:`CSSRule`上的常量 CSSRule.MOZ\_KEYFRAME\_RULE 和 CSSRule.MOZ\_KEYFRAMES\_RULE 去掉前缀成为了 CSSRule.KEYFRAME\_RULE 和 CSSRule.KEYFRAMES\_RULE.带前缀的版本仍暂时保留让开发者过度他们的代码Firefox bug 816431).
* CSSOM: 现在可以设置 `CSSMediaRule` 上的 `conditionText` 属性的值（Firefox bug 815021）。
* `DOMParser`上的 `parseFromStream` 和 `parseFromBuffer` 方法在 web 页面上被禁用.(Firefox bug 816410).
* `XMLSerializer`上的`serializeToStream`方法在 web 页面上被禁用.(Firefox bug 816410).
* `TextDecoder`和`TextEncoder`接口可以在 Worker 中使用 (Firefox bug 795542).
* 实现了 `CSS.supports()` 方法（Firefox bug 779917）。
* 实现了`UndoManager`(Firefox bug 617532).
附加组件和 Mozilla 开发者需要注意的变化
------------------------

* 移除了 nsIDOMParserJS 接口Firefox bug 816410.使用nsIDOMParser来代替。
参见
--

* Firefox 20 Aurora Release Notes
* Site Compatibility for Firefox 20
### 更早版本

* Firefox 19 for developers
* Firefox 18 for developers
* Firefox 17 for developers (en-US)
* Firefox 16 for developers (en-US)
* Firefox 15 for developers (en-US)
* Firefox 14 for developers
* Firefox 13 for developers (en-US)
* Firefox 12 for developers (en-US)
* Firefox 11 for developers (en-US)
* Firefox 10 for developers (en-US)
* Firefox 9 for developers (en-US)
* Firefox 8 for developers (en-US)
* Firefox 7 for developers (en-US)
* Firefox 6 for developers (en-US)
* Firefox 5 for developers (en-US)
* Firefox 4 for developers (en-US)
* Firefox 3.6 for developers (en-US)
* Firefox 3.5 for developers (en-US)
* Firefox 3 for developers
* Firefox 2 for developers (en-US)
* Firefox 1.5 for developers (en-US)


Firefox 119 的开发者说明 - Mozilla

Firefox 119 的开发者说明
==================

本文提供了有关 Firefox 119 中影响开发者的变更信息。Firefox 119 于 2023 年 10 月 24 日发布。

为 Web 开发者带来的变化
--------------

### HTML

#### 移除

* `<input>` 元素不再支持非标准的 `mozactionhint` 属性。请使用 `enterkeyhint` (en-US)。（详见 Firefox bug 1735980）。
### CSS

* CSS 函数 `attr()` 现在支持回退值。这样，如果缺少全局属性，就可以设置回退值（Firefox bug 1448248）。
### JavaScript

* 现在支持用于对可迭代元素进行分组的 `Object.groupBy()` 和 `Map.groupBy()` 静态方法（详见 Firefox bug 1792650）。
* `String.prototype.isWellFormed()` 和 `String.prototype.toWellFormed()` 方法可分别用于检查字符串是否包含规范的 Unicode 文本（即不包含单独代理项），并将不规范字符串清理为规范的 Unicode 文本。（详见 Firefox bug 1850755）。
### SVG

* 接受 `<length>` 值的 SVG 属性现在支持所有 SVG 元素的第 3 版 length CSS 数据类型值。这样就可以根据字体大小（`cap`、`rem` 等）、视口（`vh`、`vw`、`vmin` 等）或绝对长度（`px`、`cm` 等）确定 SVG 元素的大小，例如：`<line x1="10vw" y1="10vh" x2="50vw" y2="50vh"/>`。（详见 Firefox bug 1287054）。
### HTTP

* HTTP 响应标头 `Cross-Origin-Embedder-Policy` 的 `credentialless` 指令现已在桌面平台（以及除安卓以外的移动平台）上得到支持，其允许在未明确选择的跨源服务器上进行 `no-cors` 资源请求，尽管没有 cookie 或其他凭据（Firefox bug 1851467）。
### API

* 现在可以通过在传递给 `WebTransport.createBidirectionalStream()` (en-US) 和 `WebTransport.createUnidirectionalStream()` (en-US) 的选项参数中包含 `sendOrder` 属性，以指定发送流的相对优先级（Firefox bug 1816925）。
* 现已支持 `AuthenticatorAttestationResponse` (en-US) 接口的 `getAuthenticatorData()` (en-US)、`getPublicKeyAlgorithm()` (en-US) 和 `getPublicKey()` (en-US) 方法（详见 Firefox bug 1816519 和 Firefox bug 1816520）。
* 已支持 Web Authentication API (en-US) 的凭证属性扩展（`credProps`），允许用户在创建/注册后查询凭证是否可被发现（Firefox bug 1844437）。
* `SubtleCrypto.deriveKey()` 方法现在支持 HKDF 算法，作为其 `derivedKeyAlgorithm` 参数的选项（详见 Firefox bug 1851928）。
* 现已支持 `PublicKeyCredential` (en-US) 接口的 `parseCreationOptionsFromJSON()` (en-US)、`parseRequestOptionsFromJSON()` (en-US) 和 `toJSON()` (en-US) 方法。这些方法非常方便，可将用于创建和共享凭证对象的对象转换为 JSON 表示形式，以便进行序列化/反序列化并与服务器共享（详见 Firefox bug 1823782）。

#### DOM

* ARIA 反射现在默认支持不引用其他元素的属性；只有非 IDREF 属性才会被反射。现在，你可以通过 JavaScript API 直接获取和设置 DOM 元素上的 ARIA 属性，而不必使用 `setAttribute` 和 `getAttribute`。例如，现在除了支持 `buttonElement.setAttribute("aria-pressed", "true");` 以外，还支持 `buttonElement.ariaPressed = "true";`（Firefox bug 1785412）。
### WebDriver 一致性（WebDriver BiDi、Marionette）

#### 常规

* 在按下鼠标中键或右键的情况下执行 `pointerDown` 操作时，相关 HTML 元素发出的 `mousedown` 事件的 `buttons` 属性值被调换（Firefox bug 1850086）。
* 在执行输入类型为 `wheel` 且原点设置为 `pointer` 的 `scroll` 操作时，会不适当地引发 `invalid argument` 错误，而当前的 WebDriver 规范不支持这种组合（Firefox bug 1850166）。

#### WebDriver BiDi

* 新增了 `browsingContext.reload` 命令，允许用户重新加载当前在给定浏览上下文中显示的页面或框架（Firefox bug 1830859）。
* 新增了 `browsingContext.userPromptClosed` 事件，该事件会在 `alert`、`confirm` 或 `prompt` 类型的用户提示关闭时触发（Firefox bug 1824221）。
* 新增了 `browsingContext.navigationStarted` 事件，当 Firefox 启动新导航时会触发该事件（Firefox bug 1756595）。
* 新增了 `script.realmCreated` 和 `script.realmDestroyed` 事件，允许用户监控给定浏览上下文的 JavaScript 领域（Realm）的生命周期。这种领域基本上是一个孤立的执行环境（`sandbox`），有自己唯一的全局对象（window）（Firefox bug 1788657、Firefox bug 1788659）。
* 当打开 HTTP 身份验证对话框时，会意外发送 `browsingContext.userPromptOpened` 事件（Firefox bug 1853302）。
* 设置为 `null` 的 `context` 字段将不再发出不需要的事件。因为底层浏览上下文已关闭，此类事件不再有效（Firefox bug 1847563）。

#### Marionette

* 更新了尝试使用 `Addon:Install` 命令安装 WebExtension 时可能出现的错误代码列表，以便与 Firefox 的最新错误代码相匹配（Firefox bug 1852537）。
更早期的版本
------

* Firefox 118 for developers (en-US)
* Firefox 117 for developers (en-US)
* Firefox 116 for developers (en-US)
* Firefox 115 for developers (en-US)
* Firefox 114 for developers (en-US)
* Firefox 113 for developers (en-US)
* Firefox 112 for developers (en-US)
* Firefox 111 for developers (en-US)
* Firefox 110 for developers (en-US)
* Firefox 109 for developers (en-US)
* Firefox 108 for developers (en-US)
* Firefox 107 for developers (en-US)
* Firefox 106 for developers (en-US)
* Firefox 105 for developers (en-US)
* Firefox 104 for developers (en-US)
* Firefox 103 for developers (en-US)
* Firefox 102 for developers (en-US)
* Firefox 101 for developers (en-US)
* Firefox 100 for developers (en-US)
* Firefox 99 for developers (en-US)
* Firefox 98 for developers (en-US)
* Firefox 97 for developers (en-US)
* Firefox 96 for developers (en-US)
* Firefox 95 for developers (en-US)
* Firefox 94 for developers (en-US)
* Firefox 93 for developers (en-US)
* Firefox 92 for developers (en-US)
* Firefox 91 for developers (en-US)
* Firefox 90 for developers (en-US)
* Firefox 89 for developers (en-US)
* Firefox 88 for developers (en-US)