diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml new file mode 100644 index 00000000000..a12437f83b4 --- /dev/null +++ b/.github/linters/.markdown-lint.yml @@ -0,0 +1,38 @@ +--- +########################### +########################### +## Markdown Linter rules ## +########################### +########################### + +# Linter rules doc: +# - https://github.com/DavidAnson/markdownlint +# +# Note: +# To comment out a single error: +# +# any violations you want +# +# + +############### +# Rules by id # +############### +MD004: false # Unordered list style +MD007: false # Allow extra spaces for lists - don't cause issues and will just annoy authors +MD009: false # Allow trailing spaces - don't cause issues and will just annoy authors +MD013: false # Don't demand maximum line lengths +MD024: + siblings_only: true # Allows sub-headings to be reused under different headings +MD026: + punctuation: ".,;:!。,;:" # List of not allowed +MD029: false # Ordered list item prefix +MD033: false # Allow inline HTML +MD034: false # Allow base URLs +MD036: false # Emphasis used instead of a heading +MD040: false # Don't demand language for all code blocks + +################# +# Rules by tags # +################# +blank_lines: false # Error on blank lines diff --git a/.github/linters/.python-lint b/.github/linters/.python-lint new file mode 100644 index 00000000000..14581ee88fb --- /dev/null +++ b/.github/linters/.python-lint @@ -0,0 +1,551 @@ +[MASTER] +errors-only= + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. +jobs=1 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=yes + +# Specify a configuration file. +#rcfile= + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages +suggestion-mode=yes + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=print-statement, + parameter-unpacking, + unpacking-in-except, + old-raise-syntax, + backtick, + long-suffix, + old-ne-operator, + old-octal-literal, + import-star-module-level, + non-ascii-bytes-literal, + raw-checker-failed, + bad-inline-option, + locally-disabled, + locally-enabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + apply-builtin, + basestring-builtin, + buffer-builtin, + cmp-builtin, + coerce-builtin, + execfile-builtin, + file-builtin, + long-builtin, + raw_input-builtin, + reduce-builtin, + standarderror-builtin, + unicode-builtin, + xrange-builtin, + coerce-method, + delslice-method, + getslice-method, + setslice-method, + no-absolute-import, + old-division, + dict-iter-method, + dict-view-method, + next-method-called, + metaclass-assignment, + indexing-exception, + raising-string, + reload-builtin, + oct-method, + hex-method, + nonzero-method, + cmp-method, + input-builtin, + round-builtin, + intern-builtin, + unichr-builtin, + map-builtin-not-iterating, + zip-builtin-not-iterating, + range-builtin-not-iterating, + filter-builtin-not-iterating, + using-cmp-argument, + eq-without-hash, + div-method, + idiv-method, + rdiv-method, + exception-message-attribute, + invalid-str-codec, + sys-max-int, + bad-python3-import, + deprecated-string-function, + deprecated-str-translate-call, + deprecated-itertools-function, + deprecated-types-field, + next-method-defined, + dict-items-not-iterating, + dict-keys-not-iterating, + dict-values-not-iterating + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable=c-extension-no-member + + +[REPORTS] + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio).You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +# Activate the evaluation score. +score=no + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=optparse.Values,sys.exit + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules=flask, + flask_talisman, + matplotlib, + matplotlib.pyplot, + mistune, + pandas, + scour, + werkzeug.routing, + werkzeug.http + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + + +[BASIC] + +# Naming style matching correct argument names +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style +#argument-rgx= + +# Naming style matching correct attribute names +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style +#attr-rgx= + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo, + bar, + baz, + toto, + tutu, + tata + +# Naming style matching correct class attribute names +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style +#class-attribute-rgx= + +# Naming style matching correct class names +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming-style +#class-rgx= + +# Naming style matching correct constant names +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style +#const-rgx= + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style +#function-rgx= + +# Good variable names which should always be accepted, separated by a comma +good-names=i, + j, + k, + ex, + Run, + _ + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Naming style matching correct inline iteration names +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style +#inlinevar-rgx= + +# Naming style matching correct method names +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style +#method-rgx= + +# Naming style matching correct module names +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style +#module-rgx= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty + +# Naming style matching correct variable names +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style +#variable-rgx= + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes +max-spelling-suggestions=4 + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module +max-module-lines=1000 + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma, + dict-separator + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of statements in function / method body +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[IMPORTS] + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub, + TERMIOS, + Bastion, + rexec + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/.github/linters/.stylelintrc.json b/.github/linters/.stylelintrc.json new file mode 100644 index 00000000000..a8381cf9959 --- /dev/null +++ b/.github/linters/.stylelintrc.json @@ -0,0 +1,45 @@ +{ + "extends": "stylelint-config-standard", + "rules": { + "at-rule-no-unknown": [ + true, + { + "ignoreAtRules": ["prince-pdf"] + } + ], + "comment-empty-line-before": null, + "font-family-no-duplicate-names": [ + true, + { + "ignoreFontFamilyNames": ["monospace"] + } + ], + "length-zero-no-unit": null, + "no-descending-specificity": null, + "no-eol-whitespace": [ + true, + { + "ignore": ["empty-lines"] + } + ], + "property-no-unknown": [ + true, + { + "ignoreProperties": ["prince-pdf-display-doc-title","prince-pdf-tag-type"] + } + ], + "selector-list-comma-newline-after": null, + "selector-pseudo-element-no-unknown": [ + true, + { + "ignorePseudoElements": ["footnote-call","footnote-marker"] + } + ], + "value-keyword-case": [ + "lower", + { + "ignoreKeywords": ["Art","A4"] + } + ] + } +} diff --git a/.github/workflows/calibreapp-image-action.yml b/.github/workflows/calibreapp-image-action.yml index 2aec4740c74..c924ff6329a 100644 --- a/.github/workflows/calibreapp-image-action.yml +++ b/.github/workflows/calibreapp-image-action.yml @@ -1,3 +1,22 @@ +########################### +## Calibre Image Action ## +########################### +# +# This runs the calibre GitHub action to compress our images +# +# This Action has a few limitations: +# +# 1) This currently only works on pull requests from this repo +# and fails silently for PRs from forks. We've added a PR +# to handle this better (https://github.com/calibreapp/image-actions/pull/54) +# and after that can probably combine to the generate_chapters.yml. +# +# 2) It seems to only do a basic level of optimisations and better results can +# be achieved from https://tinypng.com/ or https://squoosh.app/ but not as automated +# so still good to have this. +# +# 3) Currently doesn't handle WebP (https://github.com/calibreapp/image-actions/issues/31) +# name: Compress images on: pull_request: diff --git a/.github/workflows/generate_chapters.yml b/.github/workflows/generate_chapters.yml index 151771bf541..b170781d1ab 100644 --- a/.github/workflows/generate_chapters.yml +++ b/.github/workflows/generate_chapters.yml @@ -1,10 +1,14 @@ +###################################### +## Custom Web Almanac GitHub action ## +###################################### +# # Updates timestamps, increments CSS, and then runs "npm run generate" # on any pushes to main for markdown, templates or generate scripts # # Then we open a Pull Request for any changes generated. # # We do it on a push, rather than on pull request, and only on main to -# avoid needing GitHub Personal access tokens and to avoid merge conflicts +# avoid needing GitHub Personal Access Tokens and to avoid merge conflicts # name: Generate Chapters on Push on: diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 00000000000..af09a3ab5e9 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,40 @@ +########################### +## Linter GitHub Actions ## +########################### +# +# Documentation: +# https://help.github.com/en/articles/workflow-syntax-for-github-actions +# +# For the Web Almanac we have the following rule changes from the defaults: +# * Markdown - we're a bit more relaxed about this since authors may be less technical +# * Python - Only change from default is to set ignored-modules=flask, flask-talisman...etc. +# * CSS - Tweaked to ignore some Prince/Normalise exceptions and some whitespace exceptions +# * JS - default rules +# * JSON - default rules +# * YML - default rules +# Exception config files are in the .github/linters directory +# +name: Lint Code Base +on: + - push + - pull_request +jobs: + lint: + name: Lint Code Base + # Skip duplicate job for local branches + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v2 + - name: Lint Code Base + uses: docker://github/super-linter:v2.2.0 + env: + VALIDATE_ALL_CODEBASE: false + DEFAULT_BRANCH: main + VALIDATE_YAML: true + VALIDATE_JSON: true + VALIDATE_PYTHON: true + VALIDATE_JAVASCRIPT_ES: true + VALIDATE_CSS: true + VALIDATE_MD: true diff --git a/sql/2020/README.md b/sql/2020/README.md index 8cc7b743828..93b6dd60fc6 100644 --- a/sql/2020/README.md +++ b/sql/2020/README.md @@ -1 +1,3 @@ +# Introduction + This is the directory for analysts of the 2020 Web Almanac to store queries for their respective chapters. diff --git a/src/README.md b/src/README.md index 550b9876d06..a74a35835c7 100644 --- a/src/README.md +++ b/src/README.md @@ -1,3 +1,7 @@ +# Developing the Web Almanac + +The Web Almanac can be developed on MacOs, Windows or Linux. It required node v12 and python v3 to be installed. + ## Run Locally Make sure you run the following commands from within the `src` directory by executing `cd src` first. diff --git a/src/content/en/2019/caching.md b/src/content/en/2019/caching.md index a9b952d4b06..4bd83caea75 100644 --- a/src/content/en/2019/caching.md +++ b/src/content/en/2019/caching.md @@ -27,12 +27,12 @@ There are three guiding principles to caching web content: cache as much as you Web architectures typically involve [multiple tiers of caching](https://blog.yoav.ws/tale-of-four-caches/). For example, an HTTP request may have the opportunity to be cached in: -* An end user's browser -* A service worker cache in the user's browser -* A shared gateway -* CDNs, which offer the ability to cache at the edge, close to end users -* A caching proxy in front of the application, to reduce the backend workload -* The application and database layers +* An end user's browser +* A service worker cache in the user's browser +* A shared gateway +* CDNs, which offer the ability to cache at the edge, close to end users +* A caching proxy in front of the application, to reduce the backend workload +* The application and database layers This chapter will explore how resources are cached within web browsers. @@ -40,22 +40,22 @@ This chapter will explore how resources are cached within web browsers. For an HTTP client to cache a resource, it needs to understand two pieces of information: -* "How long am I allowed to cache this for?" -* "How do I validate that the content is still fresh?" +* "How long am I allowed to cache this for?" +* "How do I validate that the content is still fresh?" When a web browser sends a response to a client, it typically includes headers that indicate whether the resource is cacheable, how long to cache it for, and how old the resource is. RFC 7234 covers this in more detail in section [4.2 (Freshness)](https://tools.ietf.org/html/rfc7234#section-4.2) and [4.3 (Validation)](https://tools.ietf.org/html/rfc7234#section-4.3). The HTTP response headers typically used for conveying freshness lifetime are: -* `Cache-Control` allows you to configure a cache lifetime duration (i.e. how long this is valid for). -* `Expires` provides an expiration date or time (i.e. when exactly this expires). +* `Cache-Control` allows you to configure a cache lifetime duration (i.e. how long this is valid for). +* `Expires` provides an expiration date or time (i.e. when exactly this expires). `Cache-Control` takes priority if both are present. These are [discussed in more detail below](#cache-control-vs-expires). The HTTP response headers for validating the responses stored within the cache, i.e. giving conditional requests something to compare to on the server side, are: -* `Last-Modified` indicates when the object was last changed. -* Entity Tag (`ETag`) provides a unique identifier for the content. +* `Last-Modified` indicates when the object was last changed. +* Entity Tag (`ETag`) provides a unique identifier for the content. `ETag` takes priority if both are present. These are [discussed in more detail below](#validating-freshness). @@ -105,9 +105,9 @@ If no caching headers are present in a response, then the [client is permitted t A cacheable resource is stored by the client for a period of time and available for reuse on a subsequent request. Across all HTTP requests, 80% of responses are considered cacheable, meaning that a cache is permitted to store them. Out of these, -* 6% of requests have a time to live (TTL) of 0 seconds, which immediately invalidates a cached entry. -* 27% are cached heuristically because of a missing `Cache-Control` header. -* 47% are cached for more than 0 seconds. +* 6% of requests have a time to live (TTL) of 0 seconds, which immediately invalidates a cached entry. +* 27% are cached heuristically because of a missing `Cache-Control` header. +* 47% are cached for more than 0 seconds. The remaining responses are not permitted to be stored in browser caches. @@ -254,10 +254,10 @@ In HTTP/1.0, the `Expires` header was used to indicate the date/time after which HTTP/1.1 introduced the `Cache-Control` header, and most modern clients support both headers. This header provides much more extensibility via caching directives. For example: -* `no-store` can be used to indicate that a resource should not be cached. -* `max-age` can be used to indicate a freshness lifetime. -* `must-revalidate` tells the client a cached entry must be validated with a conditional request prior to its use. -* `private` indicates a response should only be cached by a browser, and not by an intermediary that would serve multiple clients. +* `no-store` can be used to indicate that a resource should not be cached. +* `max-age` can be used to indicate a freshness lifetime. +* `must-revalidate` tells the client a cached entry must be validated with a conditional request prior to its use. +* `private` indicates a response should only be cached by a browser, and not by an intermediary that would serve multiple clients. 53% of HTTP responses include a `Cache-Control` header with the `max-age` directive, and 54% include the Expires header. However, only 41% of these responses use both headers, which means that 13% of responses are caching solely based on the older `Expires` header. @@ -343,9 +343,9 @@ For example, `cache-control: public, max-age=43200` indicates that a cached entr Figure 9 above illustrates the top 15 `Cache-Control` directives in use on mobile websites. The results for desktop and mobile are very similar. There are a few interesting observations about the popularity of these cache directives: -* `max-age` is used by almost 75% of `Cache-Control` headers, and `no-store` is used by 18%. -* `public` is rarely necessary since cached entries are assumed `public` unless `private` is specified. Approximately 38% of responses include `public`. -* The `immutable` directive is relatively new, [introduced in 2017](https://code.facebook.com/posts/557147474482256/this-browser-tweak-saved-60-of-requests-to-facebook) and is [supported on Firefox and Safari](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Browser_compatibility). Its usage has grown to 3.4%, and it is widely used in [Facebook and Google third-party responses](https://discuss.httparchive.org/t/cache-control-immutable-a-year-later/1195). +* `max-age` is used by almost 75% of `Cache-Control` headers, and `no-store` is used by 18%. +* `public` is rarely necessary since cached entries are assumed `public` unless `private` is specified. Approximately 38% of responses include `public`. +* The `immutable` directive is relatively new, [introduced in 2017](https://code.facebook.com/posts/557147474482256/this-browser-tweak-saved-60-of-requests-to-facebook) and is [supported on Firefox and Safari](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Browser_compatibility). Its usage has grown to 3.4%, and it is widely used in [Facebook and Google third-party responses](https://discuss.httparchive.org/t/cache-control-immutable-a-year-later/1195). Another interesting set of directives to show up in this list are `pre-check` and `post-check`, which are used in 2.2% of `Cache-Control` response headers (approximately 7.8 million responses). This pair of headers was [introduced in Internet Explorer 5 to provide a background validation](https://blogs.msdn.microsoft.com/ieinternals/2009/07/20/internet-explorers-cache-control-extensions/) and was rarely implemented correctly by websites. 99.2% of responses using these headers had used the combination of `pre-check=0` and `post-check=0`. When both of these directives are set to 0, then both directives are ignored. So, it seems these directives were never used correctly! @@ -357,8 +357,8 @@ When a response is not cacheable, the `Cache-Control` `no-store` directive shoul There are a few common errors that are made when attempting to configure a response to be non-cacheable: -* Setting `Cache-Control: no-cache` may sound like the resource will not be cacheable. However, the `no-cache` directive requires the cached entry to be revalidated prior to use and is not the same as being non-cacheable. -* Setting `Cache-Control: max-age=0` sets the TTL to 0 seconds, but that is not the same as being non-cacheable. When `max-age` is set to 0, the resource is stored in the browser cache and immediately invalidated. This results in the browser having to perform a conditional request to validate the resource's freshness. +* Setting `Cache-Control: no-cache` may sound like the resource will not be cacheable. However, the `no-cache` directive requires the cached entry to be revalidated prior to use and is not the same as being non-cacheable. +* Setting `Cache-Control: max-age=0` sets the TTL to 0 seconds, but that is not the same as being non-cacheable. When `max-age` is set to 0, the resource is stored in the browser cache and immediately invalidated. This results in the browser having to perform a conditional request to validate the resource's freshness. Functionally, `no-cache` and `max-age=0` are similar, since they both require revalidation of a cached resource. The `no-cache` directive can also be used alongside a `max-age` directive that is greater than 0. @@ -516,9 +516,9 @@ The `Date` HTTP response header is usually generated by the web server or CDN se Examples of some of the invalid uses of the `Expires` header are: -* Valid date formats, but using a time zone other than GMT -* Numerical values such as 0 or -1 -* Values that would be valid in a `Cache-Control` header +* Valid date formats, but using a time zone other than GMT +* Numerical values such as 0 or -1 +* Values that would be valid in a `Cache-Control` header The largest source of invalid `Expires` headers is from assets served from a popular third-party, in which a date/time uses the EST time zone, for example `Expires: Tue, 27 Apr 1971 19:44:06 EST`. diff --git a/src/content/en/2019/compression.md b/src/content/en/2019/compression.md index f4fa7910d1f..ed55bd63add 100644 --- a/src/content/en/2019/compression.md +++ b/src/content/en/2019/compression.md @@ -19,8 +19,8 @@ HTTP compression is a technique that allows you to encode information using fewe Compression algorithms are often categorized as lossy or lossless: -* When a lossy compression algorithm is used, the process is irreversible, and the original file cannot be restored via decompression. This is commonly used to compress media resources, such as image and video content where losing some data will not materially affect the resource. -* Lossless compression is a completely reversible process, and is commonly used to compress text based resources, such as [HTML](./markup), [JavaScript](./javascript), [CSS](./css), etc. +* When a lossy compression algorithm is used, the process is irreversible, and the original file cannot be restored via decompression. This is commonly used to compress media resources, such as image and video content where losing some data will not materially affect the resource. +* Lossless compression is a completely reversible process, and is commonly used to compress text based resources, such as [HTML](./markup), [JavaScript](./javascript), [CSS](./css), etc. In this chapter, we are going to explore how text-based content is compressed on the web. Analysis of non-text-based content forms part of the [Media](./media) chapter. @@ -50,9 +50,9 @@ The HTTP Archive contains measurements for 5.3 million web sites, and each site IANA maintains a [list of valid HTTP content encodings](https://www.iana.org/assignments/http-parameters/http-parameters.xml#content-coding) that can be used with the `Accept-Encoding` and `Content-Encoding` headers. These include gzip, deflate, br (brotli), as well as a few others. Brief descriptions of these algorithms are given below: -* [Gzip](https://tools.ietf.org/html/rfc1952) uses the [LZ77](https://en.wikipedia.org/wiki/LZ77_and_LZ78#LZ77) and [Huffman coding](https://en.wikipedia.org/wiki/Huffman_coding) compression techniques, and is older than the web itself. It was originally developed for the UNIX gzip program in 1992. An implementation for web delivery has existed since HTTP/1.1, and most web browsers and clients support it. -* [Deflate](https://tools.ietf.org/html/rfc1951) uses the same algorithm as gzip, just with a different container. Its use was not widely adopted for the web because of [compatibility issues](https://en.wikipedia.org/wiki/HTTP_compression#Problems_preventing_the_use_of_HTTP_compression) with some servers and browsers. -* [Brotli](https://tools.ietf.org/html/rfc7932) is a newer compression algorithm that was [invented by Google](https://github.com/google/brotli). It uses the combination of a modern variant of the LZ77 algorithm, Huffman coding, and second order context modeling. Compression via brotli is more computationally expensive compared to gzip, but the algorithm is able to reduce files by [15-25%](https://cran.r-project.org/web/packages/brotli/vignettes/brotli-2015-09-22.pdf) more than gzip compression. Brotli was first used for compressing web content in 2015 and is [supported by all modern web browsers](https://caniuse.com/#feat=brotli). +* [Gzip](https://tools.ietf.org/html/rfc1952) uses the [LZ77](https://en.wikipedia.org/wiki/LZ77_and_LZ78#LZ77) and [Huffman coding](https://en.wikipedia.org/wiki/Huffman_coding) compression techniques, and is older than the web itself. It was originally developed for the UNIX gzip program in 1992. An implementation for web delivery has existed since HTTP/1.1, and most web browsers and clients support it. +* [Deflate](https://tools.ietf.org/html/rfc1951) uses the same algorithm as gzip, just with a different container. Its use was not widely adopted for the web because of [compatibility issues](https://en.wikipedia.org/wiki/HTTP_compression#Problems_preventing_the_use_of_HTTP_compression) with some servers and browsers. +* [Brotli](https://tools.ietf.org/html/rfc7932) is a newer compression algorithm that was [invented by Google](https://github.com/google/brotli). It uses the combination of a modern variant of the LZ77 algorithm, Huffman coding, and second order context modeling. Compression via brotli is more computationally expensive compared to gzip, but the algorithm is able to reduce files by [15-25%](https://cran.r-project.org/web/packages/brotli/vignettes/brotli-2015-09-22.pdf) more than gzip compression. Brotli was first used for compressing web content in 2015 and is [supported by all modern web browsers](https://caniuse.com/#feat=brotli). Approximately 38% of HTTP responses are delivered with text-based compression. This may seem like a surprising statistic, but keep in mind that it is based on all HTTP requests in the dataset. Some content, such as images, will not benefit from these compression algorithms. The table below summarizes the percentage of requests served with each content encoding. @@ -155,9 +155,9 @@ Additionally, there are 67K requests that return an invalid `Content-Encoding`, We can't determine the compression levels from any of the diagnostics collected by the HTTP Archive, but the best practice for compressing content is: -* At a minimum, enable gzip compression level 6 for text based assets. This provides a fair trade-off between computational cost and compression ratio and is the [default for many web servers](https://paulcalvano.com/index.php/2018/07/25/brotli-compression-how-much-will-it-reduce-your-content/)—though [Nginx still defaults to the, often too low, level 1](http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_comp_level). -* If you can support brotli and precompress resources, then compress to brotli level 11. This is more computationally expensive than gzip - so precompression is an absolute must to avoid delays. -* If you can support brotli and are unable to precompress, then compress to brotli level 5. This level will result in smaller payloads compared to gzip, with a similar computational overhead. +* At a minimum, enable gzip compression level 6 for text based assets. This provides a fair trade-off between computational cost and compression ratio and is the [default for many web servers](https://paulcalvano.com/index.php/2018/07/25/brotli-compression-how-much-will-it-reduce-your-content/)—though [Nginx still defaults to the, often too low, level 1](http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_comp_level). +* If you can support brotli and precompress resources, then compress to brotli level 11. This is more computationally expensive than gzip - so precompression is an absolute must to avoid delays. +* If you can support brotli and are unable to precompress, then compress to brotli level 5. This level will result in smaller payloads compared to gzip, with a similar computational overhead. ## What types of content are we compressing? diff --git a/src/content/en/2019/ecommerce.md b/src/content/en/2019/ecommerce.md index 7d03ec5923c..2c7c911e525 100644 --- a/src/content/en/2019/ecommerce.md +++ b/src/content/en/2019/ecommerce.md @@ -17,9 +17,9 @@ last_updated: 2020-05-19T00:00:00.000Z Nearly 10% of the home pages in this study were found to be on an ecommerce platform. An "ecommerce platform" is a set of software or services that enables you to create and operate an online store. There are several types of ecommerce platforms, for example: -- **Paid-for services** such as [Shopify](https://www.shopify.com/) that host your store and help you get started. They provide website hosting, site and page templates, product-data management, shopping carts and payments. -- **Software platforms** such as [Magento Open Source](https://magento.com/products/magento-open-source) which you set up, host and manage yourself. These platforms can be powerful and flexible, but may be more complex to set up and run than services such as Shopify. -- **Hosted platforms** such as [Magento Commerce](https://magento.com/products/magento-commerce) that offer the same features as their self-hosted counterparts, except that hosting is managed as a service by a third-party. +- **Paid-for services** such as [Shopify](https://www.shopify.com/) that host your store and help you get started. They provide website hosting, site and page templates, product-data management, shopping carts and payments. +- **Software platforms** such as [Magento Open Source](https://magento.com/products/magento-open-source) which you set up, host and manage yourself. These platforms can be powerful and flexible, but may be more complex to set up and run than services such as Shopify. +- **Hosted platforms** such as [Magento Commerce](https://magento.com/products/magento-commerce) that offer the same features as their self-hosted counterparts, except that hosting is managed as a service by a third-party.
10%
diff --git a/src/content/en/2019/javascript.md b/src/content/en/2019/javascript.md index 15e042970c2..3c99e65ebc9 100644 --- a/src/content/en/2019/javascript.md +++ b/src/content/en/2019/javascript.md @@ -31,8 +31,8 @@ Sending smaller JavaScript bundles to the browser is the best way to reduce down Figure 1. Distribution of JavaScript bytes per page. -
Bar chart showing 70 bytes of JavaScript are used in the p10 percentile, 174 bytes for p25, 373 bytes for p50, 693 bytes for p75, and 1,093 bytes for p90
-
Figure 1. Distribution of JavaScript bytes per page.
+
Bar chart showing 70 bytes of JavaScript are used in the p10 percentile, 174 bytes for p25, 373 bytes for p50, 693 bytes for p75, and 1,093 bytes for p90
+
Figure 1. Distribution of JavaScript bytes per page.
Figure 1 above shows that we use 373 KB of JavaScript at the 50th percentile, or median. In other words, 50% of all sites ship more than this much JavaScript to their users. @@ -43,8 +43,8 @@ Looking at these numbers, it's only natural to wonder if this is too much JavaSc Figure 2. Distribution of JavaScript per page by device. -
Bar chart showing 76 bytes/65 bytes of JavaScript are used in the p10 percentile on desktop and mobile respectively, 186/164 bytes for p25, 391/359 bytes for p50, 721/668 bytes for p75, and 1,131/1,060 bytes for p90.
-
Figure 2. Distribution of JavaScript per page by device.
+
Bar chart showing 76 bytes/65 bytes of JavaScript are used in the p10 percentile on desktop and mobile respectively, 186/164 bytes for p25, 391/359 bytes for p50, 721/668 bytes for p75, and 1,131/1,060 bytes for p90.
+
Figure 2. Distribution of JavaScript per page by device.
At every percentile, we're sending slightly more JavaScript to desktop devices than we are to mobile. @@ -59,8 +59,8 @@ We can get an idea by analyzing main thread processing times for V8 at different Figure 3. V8 Main thread processing times by device. -
Bar chart showing 141 ms/377 ms of processing time is used in the p10 percentile on desktop and mobile respectively, 352/988 ms for p25, 849/2,437 ms for p50, 1,850/5,518 ms for p75, and 3,543/10,735 ms for p90.
-
Figure 3. V8 Main thread processing times by device.
+
Bar chart showing 141 ms/377 ms of processing time is used in the p10 percentile on desktop and mobile respectively, 352/988 ms for p25, 849/2,437 ms for p50, 1,850/5,518 ms for p75, and 3,543/10,735 ms for p90.
+
Figure 3. V8 Main thread processing times by device.
At every percentile, processing times are longer for mobile web pages than on desktop. The median total main thread time on desktop is 849 ms, while mobile is at a larger number: 2,437 ms. @@ -68,11 +68,11 @@ At every percentile, processing times are longer for mobile web pages than on de Although this data shows how much longer it can take for a mobile device to process JavaScript compared to a more powerful desktop machine, mobile devices also vary in terms of computing power. The following chart shows how processing times on a single web page can vary significantly depending on the mobile device class.
- - JavaScript processing times for Reddit.com - -
Bar chart showing 3 different devices: at the top a Pixel 3 has small amount on both the main thread and the worker thread of less than 400ms. For a Moto G4 it is approximately 900 ms on main thread and a further 300 ms on worker thread. And the final bar is an Alcatel 1X 5059D with over 2,000 ms on the main thread and over 500 ms on worker thread.
-
Figure 4. JavaScript processing times for reddit.com. From The cost of JavaScript in 2019.
+ + JavaScript processing times for Reddit.com + +
Bar chart showing 3 different devices: at the top a Pixel 3 has small amount on both the main thread and the worker thread of less than 400ms. For a Moto G4 it is approximately 900 ms on main thread and a further 300 ms on worker thread. And the final bar is an Alcatel 1X 5059D with over 2,000 ms on the main thread and over 500 ms on worker thread.
+
Figure 4. JavaScript processing times for reddit.com. From The cost of JavaScript in 2019.
### Number of requests @@ -83,8 +83,8 @@ One avenue worth exploring when trying to analyze the amount of JavaScript used Figure 5. Distribution of total JavaScript requests. -
Bar chart showing 4/4 requests for desktop and mobile respectively are used in the p10 percentile, 10/9 in p25, 19/18 in p50, 33/32 in p75 and 53/52 in p90.
-
Figure 5. Distribution of total JavaScript requests.
+
Bar chart showing 4/4 requests for desktop and mobile respectively are used in the p10 percentile, 10/9 in p25, 19/18 in p50, 33/32 in p75 and 53/52 in p90.
+
Figure 5. Distribution of total JavaScript requests.
At the median, 19 requests are sent for desktop and 18 for mobile. @@ -99,16 +99,16 @@ Third-party JavaScript can come from any external, third-party source. Ads, anal Figure 6. Distribution of first and third-party scripts on desktop. -
Bar chart showing 0/1 request on desktop are first-party and third-party respectively in p10 percentile, 2/4 in p25, 6/10 in p50, 13/21 in p75, and 24/38 in p90.
-
Figure 6. Distribution of first and third-party scripts on desktop.
+
Bar chart showing 0/1 request on desktop are first-party and third-party respectively in p10 percentile, 2/4 in p25, 6/10 in p50, 13/21 in p75, and 24/38 in p90.
+
Figure 6. Distribution of first and third-party scripts on desktop.
Figure 7. Distribution of first and third party scripts on mobile. -
Bar chart showing 0/1 request on mobile are first-party and third-party respectively in p10 percentile, 2/3 in p25, 5/9 in p50, 13/20 in p75, and 23/36 in p90.
-
Figure 7. Distribution of first and third party scripts on mobile.
+
Bar chart showing 0/1 request on mobile are first-party and third-party respectively in p10 percentile, 2/3 in p25, 5/9 in p50, 13/20 in p75, and 23/36 in p90.
+
Figure 7. Distribution of first and third party scripts on mobile.
For both mobile and desktop clients, more third-party requests are sent than first-party at every percentile. If this seems surprising, let's find out how much actual code shipped comes from third-party vendors. @@ -117,16 +117,16 @@ For both mobile and desktop clients, more third-party requests are sent than fir Figure 8. Distribution of total JavaScript downloaded on desktop. -
Bar chart showing 0/17 bytes of JavaScript are downloaded on desktop for first-party and third-party requests respectively in the p10 percentile, 11/62 in p25, 89/232 in p50, 200/525 in p75, and 404/900 in p90.
-
Figure 8. Distribution of total JavaScript downloaded on desktop.
+
Bar chart showing 0/17 bytes of JavaScript are downloaded on desktop for first-party and third-party requests respectively in the p10 percentile, 11/62 in p25, 89/232 in p50, 200/525 in p75, and 404/900 in p90.
+
Figure 8. Distribution of total JavaScript downloaded on desktop.
Figure 9. Distribution of total JavaScript downloaded on mobile. -
Bar chart showing 0/17 bytes of JavaScript are downloaded on mobile for first-party and third-party requests respectively in the p10 percentile, 6/54 in p25, 83/217 in p50, 189/477 in p75, and 380/827 in p90.
-
Figure 9. Distribution of total JavaScript downloaded on mobile.
+
Bar chart showing 0/17 bytes of JavaScript are downloaded on mobile for first-party and third-party requests respectively in the p10 percentile, 6/54 in p25, 83/217 in p50, 189/477 in p75, and 380/827 in p90.
+
Figure 9. Distribution of total JavaScript downloaded on mobile.
At the median, 89% more third-party code is used than first-party code authored by the developer for both mobile and desktop. This clearly shows that third-party code can be one of the biggest contributors to bloat. For more information on the impact of third parties, refer to the ["Third Parties"](./third-parties) chapter. @@ -148,8 +148,8 @@ How many sites are compressing their JavaScript resources? Figure 10. Percentage of sites compressing JavaScript resources with gzip or brotli. -
Bar chart showing 67%/65% of JavaScript resources are compressed with gzip on desktop and mobile respectively, and 15%/14% are compressed using Brotli.
-
Figure 10. Percentage of sites compressing JavaScript resources with gzip or brotli.
+
Bar chart showing 67%/65% of JavaScript resources are compressed with gzip on desktop and mobile respectively, and 15%/14% are compressed using Brotli.
+
Figure 10. Percentage of sites compressing JavaScript resources with gzip or brotli.
The majority of sites are compressing their JavaScript resources. Gzip encoding is used on ~64-67% of sites and Brotli on ~14%. Compression ratios are similar for both desktop and mobile. @@ -161,7 +161,7 @@ For a deeper analysis on compression, refer to the ["Compression"](./compression Open source code, or code with a permissive license that can be accessed, viewed and modified by anyone. From tiny libraries to entire browsers, such as [Chromium](https://www.chromium.org/Home) and [Firefox](https://www.openhub.net/p/firefox), open source code plays a crucial role in the world of web development. In the context of JavaScript, developers rely on open source tooling to include all types of functionality into their web page. Regardless of whether a developer decides to use a small utility library or a massive framework that dictates the architecture of their entire application, relying on open-source packages can make feature development easier and faster. So which JavaScript open-source libraries are used the most?
- +
@@ -277,7 +277,7 @@ Open source code, or code with a permissive license that can be accessed, viewed
Library
-
Figure 11. Top JavaScript libraries on desktop and mobile.
+
Figure 11. Top JavaScript libraries on desktop and mobile.
[jQuery](https://jquery.com/), the most popular JavaScript library ever created, is used in 85.03% of desktop pages and 83.46% of mobile pages. The advent of many Browser APIs and methods, such as [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) and [querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector), standardized much of the functionality provided by the library into a native form. Although the popularity of jQuery may seem to be declining, why is it still used in the vast majority of the web? @@ -299,16 +299,16 @@ In the past number of years, the JavaScript ecosystem has seen a rise in open-so Figure 12. Most frequently used frameworks on desktop. -
Bar chart showing 4.6% of sites use React, 2.0% AngularJS, 1.8% Backbone.js, 0.8% Vue.js, 0.4% Knockout.js, 0.3% Zone.js, 0.3% Angular, 0.1% AMP, 0.1% Ember.js.
-
Figure 12. Most frequently used frameworks on desktop.
+
Bar chart showing 4.6% of sites use React, 2.0% AngularJS, 1.8% Backbone.js, 0.8% Vue.js, 0.4% Knockout.js, 0.3% Zone.js, 0.3% Angular, 0.1% AMP, 0.1% Ember.js.
+
Figure 12. Most frequently used frameworks on desktop.
-Only a subset of popular frameworks are being analyzed here, but it's important to note that all of them either follow one of these two approaches: +Only a subset of popular frameworks are being analyzed here, but it's important to note that all of them either follow one of these two approaches: -- A [model-view-controller](https://developer.chrome.com/apps/app_frameworks) (or model-view-viewmodel) architecture -- A component-based architecture +- A [model-view-controller](https://developer.chrome.com/apps/app_frameworks) (or model-view-viewmodel) architecture +- A component-based architecture -Although there has been a shift towards a component-based model, many older frameworks that follow the MVC paradigm ([AngularJS](https://angularjs.org/), [Backbone.js](https://backbonejs.org/), [Ember](https://emberjs.com/)) are still being used in thousands of pages. However, [React](https://reactjs.org/), [Vue](https://vuejs.org/) and [Angular](https://angular.io/) are the most popular component-based frameworks ([Zone.js](https://github.com/angular/zone.js) is a package that is now part of Angular core). +Although there has been a shift towards a component-based model, many older frameworks that follow the MVC paradigm ([AngularJS](https://angularjs.org/), [Backbone.js](https://backbonejs.org/), [Ember](https://emberjs.com/)) are still being used in thousands of pages. However, [React](https://reactjs.org/), [Vue](https://vuejs.org/) and [Angular](https://angular.io/) are the most popular component-based frameworks ([Zone.js](https://github.com/angular/zone.js) is a package that is now part of Angular core). ## Differential loading @@ -326,8 +326,8 @@ How many sites use `type="module"` for scripts on their page? Figure 13. Percentage of sites utilizing type=module. -
Bar chart showing 0.6% of sites on desktop use 'type=module', and 0.8% of sites on mobile.
-
Figure 13. Percentage of sites utilizing type=module.
+
Bar chart showing 0.6% of sites on desktop use 'type=module', and 0.8% of sites on mobile.
+
Figure 13. Percentage of sites utilizing type=module.
Browser-level support for modules is still relatively new, and the numbers here show that very few sites currently use `type="module"` for their scripts. Many sites are still relying on module loaders (2.37% of all desktop sites use [RequireJS](https://github.com/requirejs/requirejs) for example) and bundlers ([webpack](https://webpack.js.org/) for example) to define modules within their codebase. @@ -344,8 +344,8 @@ When used together, browsers that support modules will completely ignore any scr Figure 14. Percentage of sites using nomodule. -
Bar chart showing 0.8% of sites on desktop use 'nomobule', and 0.5% of sites on mobile.
-
Figure 14. Percentage of sites using nomodule.
+
Bar chart showing 0.8% of sites on desktop use 'nomobule', and 0.5% of sites on mobile.
+
Figure 14. Percentage of sites using nomodule.
Similarly, very few sites (0.50%-0.80%) use the `nomodule` attribute for any scripts. @@ -363,8 +363,8 @@ So, how many sites use preload and prefetch directives? Figure 15. Percentage of sites using rel=preload for scripts. -
Bar chart showing 14% of sites on desktop use rel=preload' for scripts, and 15% of sites on mobile.
-
Figure 15. Percentage of sites using rel=preload for scripts.
+
Bar chart showing 14% of sites on desktop use rel=preload' for scripts, and 15% of sites on mobile.
+
Figure 15. Percentage of sites using rel=preload for scripts.
For all sites measured in HTTP Archive, 14.33% of desktop sites and 14.84% of mobile sites use `` for scripts on their page. @@ -375,8 +375,8 @@ For prefetch, we have the following: Figure 16. Percentage of sites using rel=prefetch for scripts. -
Bar chart showing 0.08% of sites on desktop use 'rel=prefetch', and 0.08% of sites on mobile.
-
Figure 16. Percentage of sites using rel=prefetch for scripts.
+
Bar chart showing 0.08% of sites on desktop use 'rel=prefetch', and 0.08% of sites on mobile.
+
Figure 16. Percentage of sites using rel=prefetch for scripts.
For both mobile and desktop, 0.08% of pages leverage prefetch for any of their scripts. @@ -400,8 +400,8 @@ How many sites use the following APIs? Figure 17. Usage of new JavaScript APIs. -
Bar chart showing 25.5%/36.2% of sites on desktop and mobile respectivdely use WeakMap, 6.1%/17.2% use WeakSet, 3.9%/14.0% use Intl, 3.9%/4.4% use Proxy, 0.4%/0.4% use Atomics, and 0.2%/0.2% use SharedArrayBuffer.
-
Figure 17. Usage of new JavaScript APIs.
+
Bar chart showing 25.5%/36.2% of sites on desktop and mobile respectivdely use WeakMap, 6.1%/17.2% use WeakSet, 3.9%/14.0% use Intl, 3.9%/4.4% use Proxy, 0.4%/0.4% use Atomics, and 0.2%/0.2% use SharedArrayBuffer.
+
Figure 17. Usage of new JavaScript APIs.
Atomics (0.38%) and SharedArrayBuffer (0.20%) are barely visible on this chart since they are used on such few pages. @@ -420,8 +420,8 @@ Although useful, there are a number of reasons why many sites may not want to in Figure 18. Percentage of sites using source maps. -
Bar chart showing 18% of desktop sites and 17% of mobile sites use source maps.
-
Figure 18. Percentage of sites using source maps.
+
Bar chart showing 18% of desktop sites and 17% of mobile sites use source maps.
+
Figure 18. Percentage of sites using source maps.
For both desktop and mobile pages, the results are about the same. 17-18% include a source map for at least one script on the page (detected as a first-party script with `sourceMappingURL`). diff --git a/src/content/en/2019/markup.md b/src/content/en/2019/markup.md index 5b5482d768e..ce5e761eee7 100644 --- a/src/content/en/2019/markup.md +++ b/src/content/en/2019/markup.md @@ -17,7 +17,7 @@ last_updated: 2020-03-01T00:00:00.000Z In 2005, Ian "Hixie" Hickson posted [some analysis of markup data](https://web.archive.org/web/20060203035414/http://code.google.com/webstats/index.html) building upon various previous work. Much of this work aimed to investigate class names to see if there were common informal semantics that were being adopted by developers which it might make sense to standardize upon. Some of this research helped inform new elements in HTML5. -14 years later, it's time to take a fresh look. Since then, we've also had the introduction of [Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) and the [Extensible Web Manifesto](https://extensiblewebmanifesto.org/) encouraging that we find better ways to pave the cowpaths by allowing developers to explore the space of elements themselves and allow standards bodies to[ act more like dictionary editors](https://bkardell.com/blog/Dropping-The-F-Bomb-On-Standards.html). Unlike CSS class names, which might be used for anything, we can be far more certain that authors who used a non-standard *element* really intended this to be an element. +14 years later, it's time to take a fresh look. Since then, we've also had the introduction of [Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) and the [Extensible Web Manifesto](https://extensiblewebmanifesto.org/) encouraging that we find better ways to pave the cowpaths by allowing developers to explore the space of elements themselves and allow standards bodies to [act more like dictionary editors](https://bkardell.com/blog/Dropping-The-F-Bomb-On-Standards.html). Unlike CSS class names, which might be used for anything, we can be far more certain that authors who used a non-standard *element* really intended this to be an element. As of July 2019, the HTTP Archive has begun collecting all used *element* names in the DOM for about 4.4 million desktop home pages, and about 5.3 million mobile home pages which we can now begin to research and dissect. _(Learn more about our [Methodology](./methodology).)_ diff --git a/src/content/en/2019/resource-hints.md b/src/content/en/2019/resource-hints.md index ae600b05097..244f67e3a0e 100644 --- a/src/content/en/2019/resource-hints.md +++ b/src/content/en/2019/resource-hints.md @@ -19,9 +19,9 @@ last_updated: 2020-03-02T00:00:00.000Z [Examples](https://youtu.be/YJGCZCaIZkQ?t=1956) of performance improvements as a result of resource hints include: -* Jabong decreased Time to Interactive by 1.5 seconds by preloading critical scripts. -* Barefoot Wine decreased Time to Interactive of future pages by 2.7 seconds by prefetching visible links. -* Chrome.com decreased latency by 0.7 seconds by preconnecting to critical origins. +* Jabong decreased Time to Interactive by 1.5 seconds by preloading critical scripts. +* Barefoot Wine decreased Time to Interactive of future pages by 2.7 seconds by prefetching visible links. +* Chrome.com decreased latency by 0.7 seconds by preconnecting to critical origins. There are four separate resource hints supported by most browsers today: `dns-prefetch`, `preconnect`, `preload`, and `prefetch`. diff --git a/src/content/en/2019/security.md b/src/content/en/2019/security.md index 06efeb00054..081081a0acd 100644 --- a/src/content/en/2019/security.md +++ b/src/content/en/2019/security.md @@ -166,7 +166,7 @@ The [HSTS](https://tools.ietf.org/html/rfc6797) header allows a website to instr
Figure 9. HSTS directive usage.
-Less than 15% of mobile and desktop pages are issuing a HSTS with a `max-age ` directive. This is a minimum requirement for a valid policy. Fewer still are including subdomains in their policy with the `includeSubDomains` directive and even fewer still are HSTS preloading. Looking at the median value for a HSTS `max-age`, for those that do use this, we can see that on both desktop and mobile it is 15768000, a strong configuration representing half a year (60 x 60 x 24 x 365/2). +Less than 15% of mobile and desktop pages are issuing a HSTS with a `max-age` directive. This is a minimum requirement for a valid policy. Fewer still are including subdomains in their policy with the `includeSubDomains` directive and even fewer still are HSTS preloading. Looking at the median value for a HSTS `max-age`, for those that do use this, we can see that on both desktop and mobile it is 15768000, a strong configuration representing half a year (60 x 60 x 24 x 365/2).
@@ -272,10 +272,10 @@ A total of 3.25% of desktop pages and 2.95% of mobile pages issue a `Referrer-Po | `no-referrer-when-downgrade` | 39.16% | 41.52% | | `strict-origin-when-cross-origin` | 39.16% | 22.17% | | `unsafe-url` | 22.17% | 22.17% | -| `same-origin ` | 7.97% | 7.97% | +| `same-origin` | 7.97% | 7.97% | | `origin-when-cross-origin` | 6.76% | 6.44% | | `no-referrer` | 5.65% | 5.38% | -| `strict-origin ` | 4.35% | 4.14% | +| `strict-origin` | 4.35% | 4.14% | | `origin` | 3.63% | 3.23% |
Figure 11. `Referrer-Policy` configuration option usage.
diff --git a/src/content/es/2019/javascript.md b/src/content/es/2019/javascript.md index e2266e2896f..13586cb4421 100644 --- a/src/content/es/2019/javascript.md +++ b/src/content/es/2019/javascript.md @@ -31,8 +31,8 @@ Enviar paquetes de JavaScript más pequeños al navegador es la mejor manera de Figura 1. Distribución de bytes de JavaScript por página. -
Gráfico de barras que muestra que 70 bytes de JavaScript se usa en el percentil p10, 174 bytes para p25, 373 bytes para p50, 693 bytes para p75 y 1.093 bytes para p90
-
Figura 1. Distribución de bytes de JavaScript por página.
+
Gráfico de barras que muestra que 70 bytes de JavaScript se usa en el percentil p10, 174 bytes para p25, 373 bytes para p50, 693 bytes para p75 y 1.093 bytes para p90
+
Figura 1. Distribución de bytes de JavaScript por página.
La Figura 1 anterior muestra que utilizamos 373 KB de JavaScript en el percentil 50, o mediana. En otras palabras, el 50% de todos los sitios envían más de este JavaScript a sus usuarios. @@ -43,8 +43,8 @@ Mirando estos números, es natural preguntarse si esto es demasiado JavaScript. Figura 2. Distribución de JavaScript por página por dispositivo. -
Gráfico de barras que muestra 76 bytes / 65 bytes de JavaScript se usa en el percentil p10 en computadoras de escritorio y dispositivos móviles respectivamente, 186/164 bytes para p25, 391/359 bytes para p50, 721/668 bytes para p75 y 1.131 / 1.060 bytes para p90 .
-
Figura 2. Distribución de JavaScript por página por dispositivo.
+
Gráfico de barras que muestra 76 bytes / 65 bytes de JavaScript se usa en el percentil p10 en computadoras de escritorio y dispositivos móviles respectivamente, 186/164 bytes para p25, 391/359 bytes para p50, 721/668 bytes para p75 y 1.131 / 1.060 bytes para p90 .
+
Figura 2. Distribución de JavaScript por página por dispositivo.
En cada percentil, estamos enviando un poco más de JavaScript a los dispositivos de escritorio que a los dispositivos móviles. @@ -59,8 +59,8 @@ Podemos tener una idea analizando los tiempos de procesamiento de subprocesos pr Figura 3. Tiempos de procesamiento de subprocesos principales según V8 por dispositivo. -
Gráfico de barras que muestra 141 ms / 377 ms de tiempo de procesamiento se utiliza en el percentil p10 en computadoras de escritorio y dispositivos móviles respectivamente, 352/988 ms para p25, 849 / 2.437 ms para p50, 1.850 / 5.518 ms para p75 y 3.543 / 10.735 ms para p90.
-
Figura 3. Tiempos de procesamiento de subprocesos principales según V8 por dispositivo.
+
Gráfico de barras que muestra 141 ms / 377 ms de tiempo de procesamiento se utiliza en el percentil p10 en computadoras de escritorio y dispositivos móviles respectivamente, 352/988 ms para p25, 849 / 2.437 ms para p50, 1.850 / 5.518 ms para p75 y 3.543 / 10.735 ms para p90.
+
Figura 3. Tiempos de procesamiento de subprocesos principales según V8 por dispositivo.
En cada percentil, los tiempos de procesamiento son más largos para las páginas web móviles que para las computadoras de escritorio. La mediana del tiempo total de subprocesos principales en el escritorio es de 849 ms, mientras que el móvil está en un número mayor: 2.437 ms. @@ -68,11 +68,11 @@ En cada percentil, los tiempos de procesamiento son más largos para las página Aunque estos datos muestran cuánto tiempo puede llevar un dispositivo móvil procesar JavaScript en comparación con una máquina de escritorio más potente, los dispositivos móviles también varían en términos de potencia informática. El siguiente cuadro muestra cómo los tiempos de procesamiento en una sola página web pueden variar significativamente según la clase de dispositivo móvil.
- - Figura 4. Tiempos de procesamiento de JavaScript para Reddit.com - -
Gráfico de barras que muestra 3 dispositivos diferentes: en la parte superior, un Pixel 3, que tiene un tiempo de procesamiento pequeño tanto en el hilo principal como en el hilo worker de menos de 400 ms. Para un Moto G4 es de aproximadamente 900 ms en el subproceso principal y otros 300 ms en el subproceso del worker. Y la barra final es un Alcatel 1X 5059D con más de 2.000 ms en el subproceso principal y más de 500 ms en el subproceso del worker.
-
Figura 4. Tiempos de procesamiento de JavaScript para Reddit.com. Tomado de El costo de JavaScript en 2019.
+ + Figura 4. Tiempos de procesamiento de JavaScript para Reddit.com + +
Gráfico de barras que muestra 3 dispositivos diferentes: en la parte superior, un Pixel 3, que tiene un tiempo de procesamiento pequeño tanto en el hilo principal como en el hilo worker de menos de 400 ms. Para un Moto G4 es de aproximadamente 900 ms en el subproceso principal y otros 300 ms en el subproceso del worker. Y la barra final es un Alcatel 1X 5059D con más de 2.000 ms en el subproceso principal y más de 500 ms en el subproceso del worker.
+
Figura 4. Tiempos de procesamiento de JavaScript para Reddit.com. Tomado de El costo de JavaScript en 2019.
### Número de Solicitudes @@ -83,8 +83,8 @@ Una vía que vale la pena explorar al tratar de analizar la cantidad de JavaScri Figura 5. Distribución del total de solicitudes de JavaScript. -
Gráfico de barras que muestra 4/4 solicitudes se utilizan para computadoras de escritorio y dispositivos móviles respectivamente en el percentil p10, 10/9 en p25, 19/18 en p50, 33/32 en p75 y 53/52 en p90.
-
Figura 5. Distribución del total de solicitudes de JavaScript.
+
Gráfico de barras que muestra 4/4 solicitudes se utilizan para computadoras de escritorio y dispositivos móviles respectivamente en el percentil p10, 10/9 en p25, 19/18 en p50, 33/32 en p75 y 53/52 en p90.
+
Figura 5. Distribución del total de solicitudes de JavaScript.
En la mediana, se envían 19 solicitudes para computadoras de escritorio y 18 para dispositivos móviles. @@ -99,16 +99,16 @@ JavaScript de contenido de terceros puede provenir de cualquier fuente externa d Figura 6. Distribución de scripts de origen y de terceros en dispositivos de escritorio. -
Gráfico de barras que muestra las solicitudes 0/1 en el escritorio es contenido de origen y contenido de terceros, respectivamente, en el percentil p10, 2/4 en la p25, 6/10 en la p50, 13/21 en la p75 y 24/38 en la p90.
-
Figura 6. Distribución de scripts de origen y de terceros en dispositivos de escritorio.
+
Gráfico de barras que muestra las solicitudes 0/1 en el escritorio es contenido de origen y contenido de terceros, respectivamente, en el percentil p10, 2/4 en la p25, 6/10 en la p50, 13/21 en la p75 y 24/38 en la p90.
+
Figura 6. Distribución de scripts de origen y de terceros en dispositivos de escritorio.
Figura 7. Distribución de scripts de origen  y de terceros en dispositivos móviles. -
Gráfico de barras que muestra las solicitudes 0/1 en dispositivos móviles es de contenido de origen y contenido de terceros, respectivamente, en el percentil p10, 2/3 en la p25, 5/9 en la p50, 13/20 en la p75 y 23/36 en la p90.
-
Figura 7. Distribución de scripts de origen y de terceros en dispositivos móviles.
+
Gráfico de barras que muestra las solicitudes 0/1 en dispositivos móviles es de contenido de origen y contenido de terceros, respectivamente, en el percentil p10, 2/3 en la p25, 5/9 en la p50, 13/20 en la p75 y 23/36 en la p90.
+
Figura 7. Distribución de scripts de origen y de terceros en dispositivos móviles.
Para clientes móviles y de escritorio, se envían más solicitudes de contenido de terceros que de contenido de origen en cada percentil. Si esto parece sorprendente, descubramos cuánto código real enviado proviene de proveedores externos. @@ -117,16 +117,16 @@ Para clientes móviles y de escritorio, se envían más solicitudes de contenido Figura 8. Distribución del JavaScript total descargado en dispositivos de escritorio. -
Gráfico de barras que muestra 0/17 bytes de JavaScript se descarga en dispositivos de escritorio para contenido de origen y contenido de terceros, respectivamente, en el percentil p10, 11/62 en p25, 89/232 en p50, 200/525 en p75 y 404/900 en p90.
-
Figura 8. Distribución del JavaScript total descargado en dispositivos de escritorio.
+
Gráfico de barras que muestra 0/17 bytes de JavaScript se descarga en dispositivos de escritorio para contenido de origen y contenido de terceros, respectivamente, en el percentil p10, 11/62 en p25, 89/232 en p50, 200/525 en p75 y 404/900 en p90.
+
Figura 8. Distribución del JavaScript total descargado en dispositivos de escritorio.
Figura 9. Distribución del JavaScript total descargado en dispositivos móviles. -
Gráfico de barras que muestra 0/17 bytes de JavaScript se descarga en dispositivos móviles para contenido de origen y contenido de terceros, respectivamente, en el percentil p10, 6/54 en p25, 83/217 en p50, 189/477 en p75 y 380/827 en p90.
-
Figura 9. Distribución del JavaScript total descargado en dispositivos móviles.
+
Gráfico de barras que muestra 0/17 bytes de JavaScript se descarga en dispositivos móviles para contenido de origen y contenido de terceros, respectivamente, en el percentil p10, 6/54 en p25, 83/217 en p50, 189/477 en p75 y 380/827 en p90.
+
Figura 9. Distribución del JavaScript total descargado en dispositivos móviles.
En la mediana, se utiliza un 89% más de código de contenido de terceros que el código de contenido de origen creado por el desarrollador para dispositivos móviles y de escritorio. Esto muestra claramente que el código de terceros puede ser uno de los mayores contribuyentes a la inflación. @@ -148,8 +148,8 @@ Los scripts comprimidos siempre deberán ser descomprimidos por el navegador una Figura 10. Porcentaje de sitios que comprimen recursos de JavaScript con gzip o brotli. -
Gráfico de barras que muestra el 67% / 65% de los recursos de JavaScript se comprime con gzip en computadoras de escritorio y dispositivos móviles respectivamente, y el 15% / 14% se comprime con Brotli.
-
Figura 10. Porcentaje de sitios que comprimen recursos de JavaScript con gzip o brotli.
+
Gráfico de barras que muestra el 67% / 65% de los recursos de JavaScript se comprime con gzip en computadoras de escritorio y dispositivos móviles respectivamente, y el 15% / 14% se comprime con Brotli.
+
Figura 10. Porcentaje de sitios que comprimen recursos de JavaScript con gzip o brotli.
La mayoría de los sitios están comprimiendo sus recursos de JavaScript. La codificación Gzip se usa en ~ 64-67% de los sitios y Brotli en ~ 14%. Las relaciones de compresión son similares tanto para computadoras de escritorio como para dispositivos móviles. @@ -163,7 +163,7 @@ Código fuente abierto, o código con una licencia permisiva a la que cualquier **¿Qué bibliotecas de código abierto de JavaScript se usan más?**
-
+
@@ -279,7 +279,7 @@ Código fuente abierto, o código con una licencia permisiva a la que cualquier
Librería
-
Figura 11. Principales bibliotecas de JavaScript en computadoras de escritorio y dispositivos móviles.
+
Figura 11. Principales bibliotecas de JavaScript en computadoras de escritorio y dispositivos móviles.
[jQuery](https://jquery.com/), la biblioteca JavaScript más popular jamás creada, se utiliza en el 85,03% de las páginas de escritorio y el 83,46% de las páginas móviles. El advenimiento de muchas API y métodos del navegador, tales como [Fetch](https://developer.mozilla.org/docs/Web/API/Fetch_API) y [querySelector](https://developer.mozilla.org/docs/Web/API/Document/querySelector), estandarizaron gran parte de la funcionalidad proporcionada por la biblioteca en una forma nativa. Aunque la popularidad de jQuery puede parecer estar disminuyendo, ¿por qué todavía se usa en la gran mayoría de la web? @@ -301,8 +301,8 @@ En los últimos años, el ecosistema de JavaScript ha visto un aumento en las bi Figura 12. Los frameworks más utilizados en el escritorio. -
Gráfico de barras que muestra que el 4,6% de los sitios usan React, 2,0% AngiularJS, 1,8% Backbone.js, 0,8% Vue.js, 0,4% Knockout.js, 0,3% Zone.js, 0,3% Angular, 0,1% AMP, 0,1% Ember. js.
-
Figura 12. Los frameworks más utilizados en el escritorio.
+
Gráfico de barras que muestra que el 4,6% de los sitios usan React, 2,0% AngiularJS, 1,8% Backbone.js, 0,8% Vue.js, 0,4% Knockout.js, 0,3% Zone.js, 0,3% Angular, 0,1% AMP, 0,1% Ember. js.
+
Figura 12. Los frameworks más utilizados en el escritorio.
Aquí solo se analiza un subconjunto de marcos populares, pero es importante tener en cuenta que todos ellos siguen uno de estos dos enfoques: @@ -330,8 +330,8 @@ Para declarar un script como módulo, la etiqueta del script debe tener el códi Figura 13. Porcentaje de sitios que utilizan type=module. -
Gráfico de barras que muestra el 0,6% de los sitios en computadoras de escritorio usan 'type=module' y el 0,8% de los sitios en dispositivos móviles.
-
Figura 13. Porcentaje de sitios que utilizan type=module.
+
Gráfico de barras que muestra el 0,6% de los sitios en computadoras de escritorio usan 'type=module' y el 0,8% de los sitios en dispositivos móviles.
+
Figura 13. Porcentaje de sitios que utilizan type=module.
El soporte a nivel de navegador para módulos todavía es relativamente nuevo, y los números aquí muestran que muy pocos sitios usan actualmente `type="module"` para sus scripts. Muchos sitios todavía dependen de cargadores de módulos (2,37% de todos los sitios de escritorio usan [RequireJS](https://github.com/requirejs/requirejs) por ejemplo) y _bundlers_ ([webpack](https://webpack.js.org/) por ejemplo) para definir módulos dentro de su código fuente. @@ -350,8 +350,8 @@ Así que, **¿Cuántos sitios usan `nomodule` para los scripts en su página?** Figura 14. Porcentaje de sitios que usan nomodule. -
Gráfico de barras que muestra el 0,8% de los sitios en computadoras de escritorio usan 'nomodule' y el 0,5% de los sitios en dispositivos móviles.
-
Figura 14. Porcentaje de sitios que usan nomodule.
+
Gráfico de barras que muestra el 0,8% de los sitios en computadoras de escritorio usan 'nomodule' y el 0,5% de los sitios en dispositivos móviles.
+
Figura 14. Porcentaje de sitios que usan nomodule.
Del mismo modo, muy pocos sitios (0,50% - 0,80%) usan el atributo `nomodule` para cualquier script. @@ -369,8 +369,8 @@ Del mismo modo, muy pocos sitios (0,50% - 0,80%) usan el atributo `nomodule` par Figura 15. Porcentaje de sitios que usan rel=preload para scripts. -
Gráfico de barras que muestra que el 14% de los sitios en computadoras de escritorio usan 'rel=preload 'para scripts, y el 15% de los sitios en dispositivos móviles.
-
Figura 15. Porcentaje de sitios que usan rel=preload para scripts.
+
Gráfico de barras que muestra que el 14% de los sitios en computadoras de escritorio usan 'rel=preload 'para scripts, y el 15% de los sitios en dispositivos móviles.
+
Figura 15. Porcentaje de sitios que usan rel=preload para scripts.
Para todos los sitios medidos en HTTP Archive, el 14.33% de los sitios de computadoras de escritorio y el 14.84% de los sitios en dispositivos móviles usan `` para los scripts en su página. @@ -381,8 +381,8 @@ Para _prefetch_: Figura 16. Porcentaje de sitios que usan rel=prefetch para scripts. -
Gráfico de barras que muestra el 0,08% de los sitios en computadoras de escritorio usan 'rel=prefetch' y el 0,08% de los sitios en dispositivos móviles.
-
Figura 16. Porcentaje de sitios que usan rel=prefetch para scripts.
+
Gráfico de barras que muestra el 0,08% de los sitios en computadoras de escritorio usan 'rel=prefetch' y el 0,08% de los sitios en dispositivos móviles.
+
Figura 16. Porcentaje de sitios que usan rel=prefetch para scripts.
Tanto para dispositivos móviles como para computadoras de escritorio, el 0,08% de las páginas aprovechan la captación previa para cualquiera de sus scripts. @@ -406,8 +406,8 @@ Con HTTP Archive, podemos echar un vistazo a cualquier API más nueva que sea co Figura 17. Uso de nuevas API de JavaScript. -
Gráfico de barras que muestra el 25,5% / 36,2% de los sitios en computadoras de escritorio y dispositivos móviles usa WeakMap, 6,1% / 17,2% usa WeakSet, 3,9% / 14,0% usa Intl, 3,9% / 4,4% usa Proxy, 0,4% / 0,4% usa Atomics, y 0,2% / 0,2% usan SharedArrayBuffer.
-
Figura 17. Uso de nuevas API de JavaScript.
+
Gráfico de barras que muestra el 25,5% / 36,2% de los sitios en computadoras de escritorio y dispositivos móviles usa WeakMap, 6,1% / 17,2% usa WeakSet, 3,9% / 14,0% usa Intl, 3,9% / 4,4% usa Proxy, 0,4% / 0,4% usa Atomics, y 0,2% / 0,2% usan SharedArrayBuffer.
+
Figura 17. Uso de nuevas API de JavaScript.
Atomics (0,38%) y SharedArrayBuffer (0,20%) son apenas visibles en este gráfico ya que se usan en tan pocas páginas. @@ -426,8 +426,8 @@ Aunque es útil, hay una serie de razones por las cuales muchos sitios pueden no Figura 18. Porcentaje de sitios que usan mapas fuente. -
Gráfico de barras que muestra el 18% de los sitios de escritorio y el 17% de los sitios móviles utilizan mapas fuente.
-
Figura 18. Porcentaje de sitios que usan mapas fuente.
+
Gráfico de barras que muestra el 18% de los sitios de escritorio y el 17% de los sitios móviles utilizan mapas fuente.
+
Figura 18. Porcentaje de sitios que usan mapas fuente.
Para las páginas de escritorio y móviles, los resultados son casi los mismos. Un 17-18% incluye un mapa fuente para al menos un script en la página (detectado como un script de contenido de origen con `sourceMappingURL`). diff --git a/src/content/es/2019/performance.md b/src/content/es/2019/performance.md index 5b75dba424f..c20b81ddd31 100644 --- a/src/content/es/2019/performance.md +++ b/src/content/es/2019/performance.md @@ -17,7 +17,7 @@ last_updated: 2020-03-01T00:00:00.000Z El rendimiento es una parte esencial de la experiencia del usuario. En [muchos sitios web](https://wpostats.com/), una mejora en la experiencia del usuario al acelerar el tiempo de carga de la página se corresponde con una mejora en las tasas de conversión. Por el contrario, cuando el rendimiento es deficiente, los usuarios no realizan conversiones con tanta frecuencia e incluso se ha observado que realizan [ráfagas de clicks](https://blog.fullstory.com/rage-clicks-turn-analytics-into-actionable-insights/) en la página como muestra de frustración. -Hay muchas formas de cuantificar el rendimiento web. Lo más importante es medir lo que realmente importa a los usuarios. Eventos como `onload` o` DOMContentLoaded` pueden no reflejar necesariamente lo que los usuarios experimentan visualmente. Por ejemplo, al cargar un cliente de correo electrónico, puede mostrar una barra de progreso mientras el contenido de la bandeja de entrada se carga de forma asincróna. El problema es que el evento `onload` no espera a que la bandeja de entrada se cargue asincrónamente. En este ejemplo, la métrica de carga que más le importa a los usuarios es el "tiempo para la bandeja de entrada", y centrarse en el evento `onload` puede ser engañoso. Por esa razón, este capítulo analizará métricas de pintado, carga e interactividad más modernas y de aplicación universal para tratar de capturar cómo los usuarios realmente están experimentando la página. +Hay muchas formas de cuantificar el rendimiento web. Lo más importante es medir lo que realmente importa a los usuarios. Eventos como `onload` o `DOMContentLoaded` pueden no reflejar necesariamente lo que los usuarios experimentan visualmente. Por ejemplo, al cargar un cliente de correo electrónico, puede mostrar una barra de progreso mientras el contenido de la bandeja de entrada se carga de forma asincróna. El problema es que el evento `onload` no espera a que la bandeja de entrada se cargue asincrónamente. En este ejemplo, la métrica de carga que más le importa a los usuarios es el "tiempo para la bandeja de entrada", y centrarse en el evento `onload` puede ser engañoso. Por esa razón, este capítulo analizará métricas de pintado, carga e interactividad más modernas y de aplicación universal para tratar de capturar cómo los usuarios realmente están experimentando la página. Hay dos tipos de datos de rendimiento: laboratorio y campo. También se les denomina pruebas sintéticas y medidas de usuario real (real-user measurement o RUM). La medición del rendimiento en el laboratorio garantiza que cada sitio web se pruebe bajo condiciones comunes y las variables como el navegador, la velocidad de conexión, la ubicación física, el estado de la memoria caché, etc., permanecen iguales. Esta garantía de consistencia hace que cada sitio web sea comparable entre sí. Por otro lado, medir el rendimiento en el campo representa cómo los usuarios realmente experimentan la web en todas las combinaciones infinitas de condiciones que nunca podríamos capturar en el laboratorio. Para los propósitos de este capítulo y para comprender las experiencias de los usuarios del mundo real, nos centraremos en los datos de campo. @@ -139,7 +139,7 @@ Otros geos de APAC cuentan una historia diferente. Tailandia, Vietnam, Indonesia
Figura 8. Diagrama de la API de Navigation Timing de los eventos en la navegación de una página.
-Para ayudar a explicar TTFB y los muchos factores que lo afectan, tomemos prestado un diagrama de la [especificación de la API de Navigation Timing](https://developer.mozilla.org/docs/Web/API/Navigation_timing_API). En la Figura 8 anterior, TTFB es la duración desde `startTime` hasta` responseStart`, que incluye todo lo que se encuentra entre: `unload`, `redirects`, `AppCache`,` DNS`, `SSL`,` TCP` y el tiempo el servidor pasa gestionando la petición. Dado ese contexto, veamos cómo los usuarios están experimentando esta métrica. +Para ayudar a explicar TTFB y los muchos factores que lo afectan, tomemos prestado un diagrama de la [especificación de la API de Navigation Timing](https://developer.mozilla.org/docs/Web/API/Navigation_timing_API). En la Figura 8 anterior, TTFB es la duración desde `startTime` hasta `responseStart`, que incluye todo lo que se encuentra entre: `unload`, `redirects`, `AppCache`, `DNS`, `SSL`, `TCP` y el tiempo el servidor pasa gestionando la petición. Dado ese contexto, veamos cómo los usuarios están experimentando esta métrica.
diff --git a/src/content/fr/2019/accessibility.md b/src/content/fr/2019/accessibility.md index 09ae98a1519..2e820047868 100644 --- a/src/content/fr/2019/accessibility.md +++ b/src/content/fr/2019/accessibility.md @@ -259,7 +259,7 @@ Les 5 premiers rôles, tous apparaissant sur 11 % des pages ou plus, sont d Nous pensons que certains des frameworks d’interface les plus populaires incluent des rôles de navigation dans leurs modèles. Cela expliquerait la prévalence d’attributs de type landmark. Si cette théorie est correcte, la mise à jour des frameworks d’interface populaires pour inclure davantage de prise en charge de l’accessibilité peut avoir un impact énorme sur l’accessibilité du web. -Un autre résultat amenant à cette conclusion est le fait que les attributs ARIA plus « avancés » mais tout aussi importants ne semblent pas du tout être utilisés. Ces attributs ne peuvent pas être facilement déployés via des frameworks d’interface, car ils doivent être personnalisés en fonction de la structure et de l’apparence visuelle de chaque site, individuellement. Par exemple, nous avons constaté que les attributs `posinset` et` setsize` n’étaient utilisés que sur 0,01 % des pages. Ces attributs indiquent à un utilisateur ou une utilisatrice de lecteur d’écran combien d’éléments se trouvent dans une liste ou un menu et quel élément est actuellement sélectionné. Ainsi, si une personne malvoyante essaie de naviguer dans un menu, il peut entendre des annonces d’index telles que : « Accueil, 1 sur 5 », « Produits, 2 sur 5 », « Téléchargements, 3 sur 5 », etc. +Un autre résultat amenant à cette conclusion est le fait que les attributs ARIA plus « avancés » mais tout aussi importants ne semblent pas du tout être utilisés. Ces attributs ne peuvent pas être facilement déployés via des frameworks d’interface, car ils doivent être personnalisés en fonction de la structure et de l’apparence visuelle de chaque site, individuellement. Par exemple, nous avons constaté que les attributs `posinset` et `setsize` n’étaient utilisés que sur 0,01 % des pages. Ces attributs indiquent à un utilisateur ou une utilisatrice de lecteur d’écran combien d’éléments se trouvent dans une liste ou un menu et quel élément est actuellement sélectionné. Ainsi, si une personne malvoyante essaie de naviguer dans un menu, il peut entendre des annonces d’index telles que : « Accueil, 1 sur 5 », « Produits, 2 sur 5 », « Téléchargements, 3 sur 5 », etc. ##### De nombreux sites tentent de rendre les modales accessibles diff --git a/src/content/fr/2019/caching.md b/src/content/fr/2019/caching.md index e69a9e5c9fe..d78b290955a 100644 --- a/src/content/fr/2019/caching.md +++ b/src/content/fr/2019/caching.md @@ -27,12 +27,12 @@ La mise en cache sur le web s'appuie sur trois principes fondamentaux : met Les architectures Web impliquent généralement [une mise en cache en plusieurs niveaux](https://blog.yoav.ws/tale-of-four-caches/). Par exemple une requête HTTP peut être mise en cache de différentes manière : -* dans le cache du navigateur ; -* dans le cache d'un service worker dans le navigateur ; -* dans une passerelle partagée ; -* au niveau des CDN, qui offrent la possibilité de mettre en cache à proximité des utilisateurs ; -* dans un proxy de cache en amont des applications pour réduire la charge sur les serveurs back-end ; -* au niveau de l'application et de la base de données. +* dans le cache du navigateur ; +* dans le cache d'un service worker dans le navigateur ; +* dans une passerelle partagée ; +* au niveau des CDN, qui offrent la possibilité de mettre en cache à proximité des utilisateurs ; +* dans un proxy de cache en amont des applications pour réduire la charge sur les serveurs back-end ; +* au niveau de l'application et de la base de données. Ce chapitre explique comment les ressources sont mises en cache dans les navigateurs Web. @@ -40,22 +40,22 @@ Ce chapitre explique comment les ressources sont mises en cache dans les navigat Pour qu'un client HTTP mette en cache une ressource, il doit répondre a deux questions : -* "Combien de temps dois-je mettre en cache ?" -* "Comment puis-je valider que le contenu est encore frais ?" +* "Combien de temps dois-je mettre en cache ?" +* "Comment puis-je valider que le contenu est encore frais ?" Lorsqu'un navigateur Web envoie une réponse à un client, il inclut généralement dans sa réponse des en-têtes qui indiquent si la ressource peut être mise en cache, pour combien de temps et quel est son âge. La RFC 7234 traite plus en détail de ce point dans la section [4.2 (Freshness)](https://tools.ietf.org/html/rfc7234#section-4.2) et [4.3 (Validation)](https://tools.ietf.org/html/rfc7234#section-4.3). Les en-têtes de réponse HTTP généralement utilisées pour transmettre la durée de vie sont : -* `Cache-Control` vous permet de configurer la durée de vie du cache (c'est-à-dire sa durée de validité). -* `Expires` fournit une date ou une heure d'expiration (c.-à-d. quand exactement celle-ci expire). +* `Cache-Control` vous permet de configurer la durée de vie du cache (c'est-à-dire sa durée de validité). +* `Expires` fournit une date ou une heure d'expiration (c.-à-d. quand exactement celle-ci expire). `Cache-Control` est prioritaire si les deux champs sont renseignés. Ces en-têtes sont [abordés plus en détail ci-dessous](#cache-control-vs-expires). Les en-têtes de réponse HTTP permettant de valider les données stockées en cache, c'est à dire donner les informations nécessaires pour comparer une ressource à sa contrepartie côté serveur : -* `Last-Modified` indique quand la ressource a été modifiée pour la dernière fois. -* `ETag` fournit l'identifiant unique d'une ressource. +* `Last-Modified` indique quand la ressource a été modifiée pour la dernière fois. +* `ETag` fournit l'identifiant unique d'une ressource. `ETag` est prioritaire si les deux en-têtes sont renseignés. Ces en-têtes sont [abordés plus en détail ci-dessous](#validation-de-la-fraîcheur-des-informations). @@ -105,9 +105,9 @@ Si aucun en-tête de mise en cache n'est renseigné dans la réponse, alors [l'a Une ressource mise en cache est stockée par le client pendant un certain temps et peut être réutilisée ultérieurement. Pour les requêtes HTTP, 80 % des réponses peuvent certainement être mises en cache, ce qui signifie qu'un système de cache peut les stocker. En dehors de ça, -* 6 % des requêtes ont un Time To Live (TTL) de 0 seconde, qui invalide immédiatement une entrée en cache. -* 27 % sont mis en cache par heuristique, à cause d'un `Cache-Control` manquant en en-tête. -* 47 % sont mis en cache pendant plus de 0 seconde. +* 6 % des requêtes ont un Time To Live (TTL) de 0 seconde, qui invalide immédiatement une entrée en cache. +* 27 % sont mis en cache par heuristique, à cause d'un `Cache-Control` manquant en en-tête. +* 47 % sont mis en cache pendant plus de 0 seconde. Les autres réponses ne peuvent pas être stockées dans le cache du navigateur. @@ -515,9 +515,9 @@ L'en-tête de réponse HTTP `Date` est généralement généré par le serveur w Voici des exemples d'utilisations incorrectes de l'en-tête `Expires` : -* Formats de date valides, mais utilisant un fuseau horaire autre que GMT -* Valeurs numériques telles que 0 ou -1 -* Valeurs qui seraient valides dans un en-tête `Cache-Control` +* Formats de date valides, mais utilisant un fuseau horaire autre que GMT +* Valeurs numériques telles que 0 ou -1 +* Valeurs qui seraient valides dans un en-tête `Cache-Control` La plus grande source d'en-têtes `Expires` invalides provient de ressources servies par une tierce partie , dans lesquels un horodatage utilise le fuseau horaire EST, par exemple `Expires: Tue, 27 Apr 1971 19:44:06 EST`. diff --git a/src/content/fr/2019/resource-hints.md b/src/content/fr/2019/resource-hints.md index db963294564..d0a75f630d4 100644 --- a/src/content/fr/2019/resource-hints.md +++ b/src/content/fr/2019/resource-hints.md @@ -19,9 +19,9 @@ Les [indices de ressources](https://www.w3.org/TR/resource-hints/) fournissent d [Quelques exemples](https://youtu.be/YJGCZCaIZkQ?t=1956) d'amélioration de performance suite à l'usage d'indices des ressources : -* Jabong a réduit son Time To Interactive de 1,5 seconde en préchargeant les scripts critiques. -* Barefoot Wine a réduit le Time To Interactive des futures pages de 2,7 secondes en préchargeant les liens visibles. -* Chrome.com a réduit sa latence de 0,7 seconde en se préconnectant à des domaines critiques. +* Jabong a réduit son Time To Interactive de 1,5 seconde en préchargeant les scripts critiques. +* Barefoot Wine a réduit le Time To Interactive des futures pages de 2,7 secondes en préchargeant les liens visibles. +* Chrome.com a réduit sa latence de 0,7 seconde en se préconnectant à des domaines critiques. La plupart des navigateurs actuels prennent en charge quatre indices de ressources distincts : `dns-prefetch`, `preconnect`, `preload` et `prefetch`. diff --git a/src/content/ja/2019/caching.md b/src/content/ja/2019/caching.md index d03fa7230de..ff00341fac8 100644 --- a/src/content/ja/2019/caching.md +++ b/src/content/ja/2019/caching.md @@ -27,12 +27,12 @@ Webコンテンツのキャッシュには、3つの基本原則があります 通常、Webアーキテクチャには[複数のキャッシュ層](https://blog.yoav.ws/tale-of-four-caches/)が含まれます。たとえば、HTTPリクエストは次の場所にキャッシュされる可能性があります。 -* エンドユーザーのブラウザ -* ユーザーのブラウザーのService Workerキャッシュ -* 共有ゲートウェイ -* エンドユーザーに近い側でキャッシュする機能を提供するCDN -* バックエンドの仕事長を削減するための、アプリケーションの前のキャッシングプロキシ -* アプリケーション層とデータベース層 +* エンドユーザーのブラウザ +* ユーザーのブラウザーのService Workerキャッシュ +* 共有ゲートウェイ +* エンドユーザーに近い側でキャッシュする機能を提供するCDN +* バックエンドの仕事長を削減するための、アプリケーションの前のキャッシングプロキシ +* アプリケーション層とデータベース層 この章では、Webブラウザー内でリソースがキャッシュされる方法について見ていきましょう。 @@ -40,22 +40,22 @@ Webコンテンツのキャッシュには、3つの基本原則があります HTTPクライアントがリソースをキャッシュするには、2つの情報を理解する必要があります。 -* 「これをキャッシュできる期間はどれくらいですか?」 -* 「コンテンツがまだ新しいことを検証するにはどうすればよいですか?」 +* 「これをキャッシュできる期間はどれくらいですか?」 +* 「コンテンツがまだ新しいことを検証するにはどうすればよいですか?」 Webブラウザーがクライアントにレスポンスを送信するとき、通常リソースにキャッシュ可能か、キャッシュする期間、リソースの古さを示すヘッダーが含まれます。 RFC 7234は、これをセクション[4.2(新しさ)](https://tools.ietf.org/html/rfc7234#section-4.2)および[4.3(検証)](https://tools.ietf.org/html/rfc7234#section-4.3)でより詳細にカバーしています。 通常、有効期間を伝えるために使用されるHTTPレスポンスヘッダーは次のとおりです。 -* `Cache-Control` キャッシュの生存期間(つまり、有効期間)を設定できます。 -* `Expires` 有効期限の日付または時刻を提供します(つまり、期限切れになるとき)。 +* `Cache-Control` キャッシュの生存期間(つまり、有効期間)を設定できます。 +* `Expires` 有効期限の日付または時刻を提供します(つまり、期限切れになるとき)。 `Cache-Control` 両方が存在する場合に優先されます。これらについては、[以下で詳しく説明します](#cache-controlとexpires)。 キャッシュ内に保存された応答を検証するためのHTTPレスポンスヘッダー、つまりサーバー側で比較するため、条件付き要求を提供するHTTPレスポンスヘッダーは次のとおりです。 -* `Last-Modified` オブジェクトが最後に変更された日時を示します。 -* エンティティタグ (`ETag`) コンテンツの一意の識別子を提供します。 +* `Last-Modified` オブジェクトが最後に変更された日時を示します。 +* エンティティタグ (`ETag`) コンテンツの一意の識別子を提供します。 `ETag` 両方が存在する場合に優先されます。これらについては、以下で詳しく説明します。 @@ -105,9 +105,9 @@ Webブラウザーがクライアントにレスポンスを送信するとき キャッシュ可能なリソースは、クライアントによって一定期間保存され、後続のリクエストで再利用できます。すべてのHTTPリクエスト全体で、レスポンスの80%はキャッシュ可能と見なされます。つまり、キャッシュがそれらを格納することを許可されています。 -* 要求の6%のTime To Time(TTL)は0秒で、キャッシュされたエントリはすぐに無効になります。 -* 27%は`Cache-Control`ヘッダーがないため、ヒューリスティックにキャッシュされます。 -* 47%は0秒以上キャッシュされます。 +* 要求の6%のTime To Time(TTL)は0秒で、キャッシュされたエントリはすぐに無効になります。 +* 27%は`Cache-Control`ヘッダーがないため、ヒューリスティックにキャッシュされます。 +* 47%は0秒以上キャッシュされます。 残りのレスポンスは、ブラウザーのキャッシュに保存できません。 @@ -254,10 +254,10 @@ HTTP/1.0では、`Expires`ヘッダーは、レスポンスが古くなったと HTTP/1.1は`Cache-Control`ヘッダーを導入し、最新のクライアントのほとんどは両方のヘッダーをサポートしています。このヘッダーは、キャッシングディレクティブを介して、はるかに高い拡張性を提供します。例えば。 -* `no-store` リソースをキャッシュしないことを示すために使用できます。 -* `max-age` 鮮度の寿命を示すために使用できます。 -* `must-revalidate` キャッシュされたエントリは、使用する前に条件付きリクエストで検証する必要があることをクライアントに伝えます。 -* `private` レスポンスはブラウザによってのみキャッシュされ、複数のクライアントにサービスを提供する仲介者によってキャッシュされるべきではないことを示します。 +* `no-store` リソースをキャッシュしないことを示すために使用できます。 +* `max-age` 鮮度の寿命を示すために使用できます。 +* `must-revalidate` キャッシュされたエントリは、使用する前に条件付きリクエストで検証する必要があることをクライアントに伝えます。 +* `private` レスポンスはブラウザによってのみキャッシュされ、複数のクライアントにサービスを提供する仲介者によってキャッシュされるべきではないことを示します。 HTTPレスポンスの53%は、`max-age`ディレクティブを持つ`Cache-Control`ヘッダーが含まれ、54%はExpiresヘッダーが含まれます。ただし、これらのレスポンスの41%のみが両方のヘッダーを使用します。つまり、レスポンスの13%が古い`Expires`ヘッダーのみに基づいてキャッシュされます。 @@ -343,9 +343,9 @@ HTTP/1.1[仕様](https://tools.ietf.org/html/rfc7234#section-5.2.1)には、`Cac 上記の図9は、モバイルWebサイトで使用されている上位15の`Cache-Control`ディレクティブを示しています。デスクトップとモバイルの結果は非常に似ています。これらのキャッシュディレクティブの人気について、興味深い観察結果がいくつかあります。 -* `max-age`は`Cache-Control`ヘッダーのほぼ75%で使用され、`no-store`は18%で使用されます。 -* `private`が指定されない限り、キャッシュされたエントリは`public`であると想定されるため、`public`が必要になることはほとんどありません。回答の約38%に`public`が含まれています。 -* `immutable`ディレクティブは比較的新しく、[2017年に導入](https://code.facebook.com/posts/557147474482256/this-browser-tweak-saved-60-of-requests-to-facebook)され、[FirefoxおよびSafariでサポート](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Browser_compatibility)されています。その使用率は3.4%に拡大し、[Facebook、Googleのサードパーティのレスポンス](https://discuss.httparchive.org/t/cache-control-immutable-a-year-later/1195)で広く使用されています。 +* `max-age`は`Cache-Control`ヘッダーのほぼ75%で使用され、`no-store`は18%で使用されます。 +* `private`が指定されない限り、キャッシュされたエントリは`public`であると想定されるため、`public`が必要になることはほとんどありません。回答の約38%に`public`が含まれています。 +* `immutable`ディレクティブは比較的新しく、[2017年に導入](https://code.facebook.com/posts/557147474482256/this-browser-tweak-saved-60-of-requests-to-facebook)され、[FirefoxおよびSafariでサポート](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Browser_compatibility)されています。その使用率は3.4%に拡大し、[Facebook、Googleのサードパーティのレスポンス](https://discuss.httparchive.org/t/cache-control-immutable-a-year-later/1195)で広く使用されています。 このリストに表示される別の興味深いディレクティブセットは、`pre-check`と`post-check`です。これらは、`Cache-Control`レスポンスヘッダーの2.2%(約780万件のレスポンス)で使用されます。このヘッダーのペアは、[バックグラウンドで検証を提供するためにInternet Explorer 5で導入された](https://blogs.msdn.microsoft.com/ieinternals/2009/07/20/internet-explorers-cache-control-extensions/)ものですが、Webサイトによって正しく実装されることはほとんどありませんでした。これらのヘッダーを使用したレスポンスの99.2%は、`pre-check=0`と`post-check=0`の組み合わせを使用していました。これらのディレクティブの両方が0に設定されている場合、両方のディレクティブは無視されます。したがって、これらのディレクティブは正しく使用されなかったようです! @@ -357,8 +357,8 @@ HTTP/1.1[仕様](https://tools.ietf.org/html/rfc7234#section-5.2.1)には、`Cac レスポンスをキャッシュ不可に設定しようとすると、いくつかの一般的なエラーが発生します。 -* `Cache-Control: no-cache`の設定は、リソースがキャッシュできないように聞こえるかもしれません。ただし、`no-cache`ディレクティブでは、使用する前にキャッシュされたエントリを再検証する必要があり、キャッシュ不可と同じではありません。 -* `Cache-Control: max-age = 0`を設定すると、TTLが0秒に設定されますが、これはキャッシュ不可と同じではありません。 max-ageを0に設定すると、リソースはブラウザーのキャッシュに保存され、すぐに無効になります。これにより、ブラウザは条件付きリクエストを実行してリソースの新しさを検証する必要があります。 +* `Cache-Control: no-cache`の設定は、リソースがキャッシュできないように聞こえるかもしれません。ただし、`no-cache`ディレクティブでは、使用する前にキャッシュされたエントリを再検証する必要があり、キャッシュ不可と同じではありません。 +* `Cache-Control: max-age = 0`を設定すると、TTLが0秒に設定されますが、これはキャッシュ不可と同じではありません。 max-ageを0に設定すると、リソースはブラウザーのキャッシュに保存され、すぐに無効になります。これにより、ブラウザは条件付きリクエストを実行してリソースの新しさを検証する必要があります。 機能的には、`no-cache`と`max-age=0`は似ています。どちらもキャッシュされたリソースの再検証を必要とするためです。 `no-cache`ディレクティブは、0より大きい`max-age`ディレクティブと一緒に使用することもできます。 @@ -516,9 +516,9 @@ HTTP/1.1[仕様](https://tools.ietf.org/html/rfc7234#section-5.2.1)には、`Cac `Expires`ヘッダーの無効な使用の例は次のとおりです。 -* 有効な日付形式ですが、GMT以外のタイムゾーンを使用しています -* 0や-1などの数値 -* `Cache-Control`ヘッダーで有効な値 +* 有効な日付形式ですが、GMT以外のタイムゾーンを使用しています +* 0や-1などの数値 +* `Cache-Control`ヘッダーで有効な値 無効な`Expires`ヘッダーの最大のソースは、人気のあるサードパーティから提供されるアセットからのものです。たとえば、`Expires:Tue、27 Apr 1971 19:44:06 EST`など、日付/時刻はESTタイムゾーンを使用します。 diff --git a/src/content/ja/2019/compression.md b/src/content/ja/2019/compression.md index b5434798580..d3dda467302 100644 --- a/src/content/ja/2019/compression.md +++ b/src/content/ja/2019/compression.md @@ -19,8 +19,8 @@ HTTP圧縮は、元の表現よりも少ないビットを使用して情報を 圧縮アルゴリズムは、多くの場合、非可逆または可逆に分類されます。 -* 非可逆圧縮アルゴリズムが使用される場合、プロセスは不可逆的であり、元のファイルを圧縮解除しても復元できません。これは一般に、一部のデータを失ってもリソースに重大な影響を与えない画像やビデオコンテンツなどのメディアリソースを圧縮するために使用されます。 -* ロスレス圧縮は完全に可逆的なプロセスであり、[HTML](./markup)、[JavaScript](./javascript)、[CSS](./css)などのテキストベースのリソースを圧縮するために一般的に使用されます。 +* 非可逆圧縮アルゴリズムが使用される場合、プロセスは不可逆的であり、元のファイルを圧縮解除しても復元できません。これは一般に、一部のデータを失ってもリソースに重大な影響を与えない画像やビデオコンテンツなどのメディアリソースを圧縮するために使用されます。 +* ロスレス圧縮は完全に可逆的なプロセスであり、[HTML](./markup)、[JavaScript](./javascript)、[CSS](./css)などのテキストベースのリソースを圧縮するために一般的に使用されます。 この章では、テキストベースのコンテンツがWeb上でどのように圧縮されるかを検討します。非テキストベースのコンテンツの分析は、[メディア](./media)の章の一部を形成します。 @@ -50,9 +50,9 @@ HTTP Archiveには、530万のWebサイトの測定値が含まれており、 IANAは、`Accept-Encoding`および`Content-Encoding`ヘッダーで使用できる有効な[HTTPコンテンツエンコーディングのリスト](https://www.iana.org/assignments/http-parameters/http-parameters.xml#content-coding)を保持しています。これらには、gzip、deflate、br(brotli)などが含まれます。これらのアルゴリズムの簡単な説明を以下に示します。 -* [Gzip](https://tools.ietf.org/html/rfc1952)は、[LZ77](https://ja.wikipedia.org/wiki/LZ77)および[ハフマンコーディング](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%95%E3%83%9E%E3%83%B3%E7%AC%A6%E5%8F%B7)圧縮技術を使用しており、Web自体よりも古い。もともと1992年にUNIX gzipプログラム用として開発されました。HTTP/ 1.1以降、Web配信の実装が存在し、ほとんどのブラウザーとクライアントがそれをサポートしています。 -* [Deflate](https://tools.ietf.org/html/rfc1951)はgzipと同じアルゴリズムを使用しますが、コンテナは異なります。一部のサーバーおよびブラウザとの互換性の問題のため、Webでの使用は広く採用されていません。 -* [Brotli](https://tools.ietf.org/html/rfc7932)は、[Googleが発明](https://github.com/google/brotli)した新しい圧縮アルゴリズムです。 LZ77アルゴリズムの最新のバリアント、ハフマンコーディング、および2次コンテキストモデリングの組み合わせを使用します。 Brotliを介した圧縮はgzipと比較して計算コストが高くなりますが、アルゴリズムはgzip圧縮よりもファイルを[15〜25%](https://cran.r-project.org/web/packages/brotli/vignettes/brotli-2015-09-22.pdf)削減できます。 Brotliは2015年にWebコンテンツの圧縮に初めて使用され、[すべての最新のWebブラウザーでサポートされています](https://caniuse.com/#feat=brotli)。 +* [Gzip](https://tools.ietf.org/html/rfc1952)は、[LZ77](https://ja.wikipedia.org/wiki/LZ77)および[ハフマンコーディング](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%95%E3%83%9E%E3%83%B3%E7%AC%A6%E5%8F%B7)圧縮技術を使用しており、Web自体よりも古い。もともと1992年にUNIX gzipプログラム用として開発されました。HTTP/ 1.1以降、Web配信の実装が存在し、ほとんどのブラウザーとクライアントがそれをサポートしています。 +* [Deflate](https://tools.ietf.org/html/rfc1951)はgzipと同じアルゴリズムを使用しますが、コンテナは異なります。一部のサーバーおよびブラウザとの互換性の問題のため、Webでの使用は広く採用されていません。 +* [Brotli](https://tools.ietf.org/html/rfc7932)は、[Googleが発明](https://github.com/google/brotli)した新しい圧縮アルゴリズムです。 LZ77アルゴリズムの最新のバリアント、ハフマンコーディング、および2次コンテキストモデリングの組み合わせを使用します。 Brotliを介した圧縮はgzipと比較して計算コストが高くなりますが、アルゴリズムはgzip圧縮よりもファイルを[15〜25%](https://cran.r-project.org/web/packages/brotli/vignettes/brotli-2015-09-22.pdf)削減できます。 Brotliは2015年にWebコンテンツの圧縮に初めて使用され、[すべての最新のWebブラウザーでサポートされています](https://caniuse.com/#feat=brotli)。 HTTPレスポンスの約38%はテキストベースの圧縮で配信されます。これは驚くべき統計のように思えるかもしれませんが、データセット内のすべてのHTTP要求に基づいていることに留意してください。画像などの一部のコンテンツは、これらの圧縮アルゴリズムの恩恵を受けません。次の表は、各コンテンツエンコーディングで処理されるリクエストの割合をまとめたものです。 @@ -155,9 +155,9 @@ HTTPレスポンスの約38%はテキストベースの圧縮で配信され HTTP Archiveによって収集された診断から圧縮レベルを判断することはできませんが、コンテンツを圧縮するためのベストプラクティスは次のとおりです。 -* 少なくとも、テキストベースのアセットに対してgzip圧縮レベル6を有効にします。これは、計算コストと圧縮率の間の公平なトレードオフを提供し、[多くのWebサーバーのデフォルト](https://paulcalvano.com/index.php/2018/07/25/brotli-compression-how-much-will-it-reduce-your-content/)にもかかわらず、[Nginxは依然として低すぎることが多いレベル1のままです](http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_comp_level)。 -* brotliおよびprecompressリソースをサポートできる場合は、brotliレベル11に圧縮します。これはgzipよりも計算コストが高くなります。したがって、遅延を避けるためには、事前圧縮が絶対に必要です。 -* brotliをサポートでき、事前圧縮できない場合は、brotliレベル5に圧縮します。このレベルでは、gzipと比較してペイロードが小さくなり、同様の計算オーバーヘッドが発生します。 +* 少なくとも、テキストベースのアセットに対してgzip圧縮レベル6を有効にします。これは、計算コストと圧縮率の間の公平なトレードオフを提供し、[多くのWebサーバーのデフォルト](https://paulcalvano.com/index.php/2018/07/25/brotli-compression-how-much-will-it-reduce-your-content/)にもかかわらず、[Nginxは依然として低すぎることが多いレベル1のままです](http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_comp_level)。 +* brotliおよびprecompressリソースをサポートできる場合は、brotliレベル11に圧縮します。これはgzipよりも計算コストが高くなります。したがって、遅延を避けるためには、事前圧縮が絶対に必要です。 +* brotliをサポートでき、事前圧縮できない場合は、brotliレベル5に圧縮します。このレベルでは、gzipと比較してペイロードが小さくなり、同様の計算オーバーヘッドが発生します。 ## どの種類のコンテンツを圧縮していますか? diff --git a/src/content/ja/2019/ecommerce.md b/src/content/ja/2019/ecommerce.md index 1151fc3aee2..f3abbc7febe 100644 --- a/src/content/ja/2019/ecommerce.md +++ b/src/content/ja/2019/ecommerce.md @@ -17,9 +17,9 @@ last_updated: 2020-05-19T00:00:00.000Z この調査では、ホームページの10%近くがEコマース・プラットフォーム上にあることが判明しました。「Eコマースプラットフォーム」は、オンラインストアを作成し、運営することを可能にするソフトウェアまたはサービスのセットです。Eコマースプラットフォームのいくつかのタイプがあります。 -- [Shopify](https://www.shopify.com/)のような**有料サービス**は、あなたのお店をホストし、あなたが始めるのを手助けしてくれます。彼らはウェブサイトのホスティング、サイトやページのテンプレート、商品データの管理、ショッピングカートや支払いを提供しています。 -- [Magento Open Source](https://magento.com/products/magento-open-source)のような**ソフトウェアプラットフォーム**は自分で設定し、ホストし、管理できます。これらのプラットフォームは強力で柔軟性がありますが、Shopifyのようなサービスよりもセットアップや運用が複雑になることがあります。 -- [Magento Commerce](https://magento.com/products/magento-commerce)のような**ホスト付きプラットフォーム**は、ホスティングがサードパーティによってサービスとして管理されていることを除いて、彼らのセルフホスティングされた対応と同じ機能を提供しています。 +- [Shopify](https://www.shopify.com/)のような**有料サービス**は、あなたのお店をホストし、あなたが始めるのを手助けしてくれます。彼らはウェブサイトのホスティング、サイトやページのテンプレート、商品データの管理、ショッピングカートや支払いを提供しています。 +- [Magento Open Source](https://magento.com/products/magento-open-source)のような**ソフトウェアプラットフォーム**は自分で設定し、ホストし、管理できます。これらのプラットフォームは強力で柔軟性がありますが、Shopifyのようなサービスよりもセットアップや運用が複雑になることがあります。 +- [Magento Commerce](https://magento.com/products/magento-commerce)のような**ホスト付きプラットフォーム**は、ホスティングがサードパーティによってサービスとして管理されていることを除いて、彼らのセルフホスティングされた対応と同じ機能を提供しています。
10%
diff --git a/src/content/ja/2019/fonts.md b/src/content/ja/2019/fonts.md index 7bda4925cbe..0b5432b6abd 100644 --- a/src/content/ja/2019/fonts.md +++ b/src/content/ja/2019/fonts.md @@ -577,7 +577,7 @@ Webフォントのリクエストがデスクトップとモバイルの間で パフォーマンス最適化プラグインは、あなたのパフォーマンスをはるかに悪化させることができることを皮肉っています! -## `Unicode-range`を使うとより正確なマッチングが可能になります。 +## `Unicode-range`を使うとより正確なマッチングが可能になります
56%
diff --git a/src/content/ja/2019/javascript.md b/src/content/ja/2019/javascript.md index ab22a52ab58..0b4f0325ec6 100644 --- a/src/content/ja/2019/javascript.md +++ b/src/content/ja/2019/javascript.md @@ -31,8 +31,8 @@ JavaScriptは、私たちがブラウザに送るリソースの中で最もコ
図1. ページあたりのJavaScriptバイト数の分布 -
p10パーセンタイルで70バイト、p25で174バイト、p50で373バイト、p75で693バイト、p90で1,093バイトのJavaScriptを使用していることを示す棒グラフ
-
図1. ページあたりのJavaScriptバイト数の分布
+
p10パーセンタイルで70バイト、p25で174バイト、p50で373バイト、p75で693バイト、p90で1,093バイトのJavaScriptを使用していることを示す棒グラフ
+
図1. ページあたりのJavaScriptバイト数の分布
上の図1を見ると、JavaScriptを373KB使用しているのは、50パーセンタイル(中央値)であることがわかります。つまり、全サイトの5%がこれだけのJavaScriptをユーザーに提供していることになります。 @@ -43,8 +43,8 @@ JavaScriptは、私たちがブラウザに送るリソースの中で最もコ 図2. デバイス別のページあたりのJavaScriptの分布。 -
デスクトップとモバイルでそれぞれp10パーセンタイルで76バイト/65バイトのJavaScriptを使用していることを示す棒グラフで、p25で186/164バイト、p50で391/359バイト、p75で721/668バイト、p90で1,131/1,060バイトとなっています。
-
図2. デバイス別のページあたりのJavaScriptの分布。
+
デスクトップとモバイルでそれぞれp10パーセンタイルで76バイト/65バイトのJavaScriptを使用していることを示す棒グラフで、p25で186/164バイト、p50で391/359バイト、p75で721/668バイト、p90で1,131/1,060バイトとなっています。
+
図2. デバイス別のページあたりのJavaScriptの分布。
どのパーセンタイルでも、モバイルよりもデスクトップデバイスに送信するJavaScriptの数がわずかに多くなっています。 @@ -59,8 +59,8 @@ V8のメインスレッドの処理時間を異なるパーセンタイルで分 図3. デバイス別のV8メインスレッド処理時間。 -
処理時間をデスクトップとモバイルでそれぞれp10パーセンタイルで141ms/377ms、p25で352/988ms、p50で849/2,437ms、p75で1,850/5,518ms、p90で3,543/10,735msとした棒グラフ。
-
図3. デバイス別のV8メインスレッド処理時間。
+
処理時間をデスクトップとモバイルでそれぞれp10パーセンタイルで141ms/377ms、p25で352/988ms、p50で849/2,437ms、p75で1,850/5,518ms、p90で3,543/10,735msとした棒グラフ。
+
図3. デバイス別のV8メインスレッド処理時間。
すべてのパーセンタイルにおいて、処理時間はデスクトップよりもモバイルの方が長くなっています。メインスレッドの合計時間の中央値はデスクトップでは849msであるのに対し、モバイルでは2,437msと大きくなっています。 @@ -68,11 +68,11 @@ V8のメインスレッドの処理時間を異なるパーセンタイルで分 このデータはモバイルデバイスがJavaScriptを処理するのにかかる時間が、より強力なデスクトップマシンに比べてどれだけ長いかを示していますが、モバイルデバイスは計算能力の点でも違いがあります。次の表は、1つのWebページの処理時間がモバイルデバイスのクラスによって大きく異なることを示しています。
- - Reddit.comのJavaScript処理時間 - -
3つの異なるデバイスを示す棒グラフ: 上部のPixel3は、メインスレッドとワーカースレッドの両方で400ms未満と量が少ないです。Moto G4の場合、メインスレッドで約900ms、ワーカースレッドでさらに300msです。そして最後のバーはAlcatel 1X 5059Dで、メインスレッドで2,000ms以上、ワーカースレッドで500ms以上となっています。
-
図4. reddit.comのJavaScript処理時間。2019年のJavaScriptのコストより。
+ + Reddit.comのJavaScript処理時間 + +
3つの異なるデバイスを示す棒グラフ: 上部のPixel3は、メインスレッドとワーカースレッドの両方で400ms未満と量が少ないです。Moto G4の場合、メインスレッドで約900ms、ワーカースレッドでさらに300msです。そして最後のバーはAlcatel 1X 5059Dで、メインスレッドで2,000ms以上、ワーカースレッドで500ms以上となっています。
+
図4. reddit.comのJavaScript処理時間。2019年のJavaScriptのコストより。
### リクエスト数 @@ -83,8 +83,8 @@ Webページで使用されているJavaScriptの量を分析しようとする 図5. 総JavaScriptリクエスト数の分布。 -
p10パーセンタイルではデスクトップとモバイルそれぞれ4/4のリクエストを示す棒グラフ、p25では10/9、p50では19/18、p75では33/32、p90では53/52が使用されています。
-
図5. 総JavaScriptリクエスト数の分布。
+
p10パーセンタイルではデスクトップとモバイルそれぞれ4/4のリクエストを示す棒グラフ、p25では10/9、p50では19/18、p75では33/32、p90では53/52が使用されています。
+
図5. 総JavaScriptリクエスト数の分布。
中央値では、デスクトップ用に19件、モバイル用に18件のリクエストが送信されています。 @@ -99,16 +99,16 @@ Webページで使用されているJavaScriptの量を分析しようとする 図6. デスクトップ上のファーストスクリプトとサードパーティスクリプトの分布。 -
デスクトップ上でp10パーセンタイルでは0/1リクエストがファーストパーティとサードパーティであることを示す棒グラフが表示されています、p25では2/4、p50では6/10、p75では13/21、p90では24/38となっています。
-
図6. デスクトップ上のファーストスクリプトとサードパーティスクリプトの分布。
+
デスクトップ上でp10パーセンタイルでは0/1リクエストがファーストパーティとサードパーティであることを示す棒グラフが表示されています、p25では2/4、p50では6/10、p75では13/21、p90では24/38となっています。
+
図6. デスクトップ上のファーストスクリプトとサードパーティスクリプトの分布。
図7. モバイル上のファーストパーティとサードパーティのスクリプトの分布。 -
モバイルでp10パーセンタイルでは0/1リクエストがファーストパーティとサードパーティであることを示す棒グラフが表示されています、p25では2/3、p50では5/9、p75では13/20、p90では23/36となっています。
-
図7. モバイル上のファーストパーティとサードパーティのスクリプトの分布。
+
モバイルでp10パーセンタイルでは0/1リクエストがファーストパーティとサードパーティであることを示す棒グラフが表示されています、p25では2/3、p50では5/9、p75では13/20、p90では23/36となっています。
+
図7. モバイル上のファーストパーティとサードパーティのスクリプトの分布。
モバイルクライアントとデスクトップクライアントの両方において、すべてのパーセンタイルにおいて、ファーストパーティよりもサードパーティのリクエストの方が多く送信されています。これが意外に思える場合は、実際に提供されるコードのうち、サードパーティのベンダーからのものがどれくらいあるのかを調べてみましょう。 @@ -117,16 +117,16 @@ Webページで使用されているJavaScriptの量を分析しようとする 図8. デスクトップ上でダウンロードされたJavaScriptの総ダウンロード数の分布。 -
p10パーセンタイルでは、ファーストパーティとサードパーティのリクエストに対してデスクトップ上で0/17バイトのJavaScriptがダウンロードされていることを示す棒グラフ、p25では11/62、p50では89/232、p75では200/525、p90では404/900である。
-
図8. デスクトップ上でダウンロードされたJavaScriptの総ダウンロード数の分布。
+
p10パーセンタイルでは、ファーストパーティとサードパーティのリクエストに対してデスクトップ上で0/17バイトのJavaScriptがダウンロードされていることを示す棒グラフ、p25では11/62、p50では89/232、p75では200/525、p90では404/900である。
+
図8. デスクトップ上でダウンロードされたJavaScriptの総ダウンロード数の分布。
図9. モバイルでダウンロードされたJavaScriptの総ダウンロード数の分布。 -
棒グラフは、p10パーセンタイルではファーストパーティとサードパーティのリクエストでそれぞれ0/17バイトの JavaScriptがモバイルでダウンロードされていることを示していますが、p25では6/54、p50では83/217、p75では189/477、p90では380/827です。
-
図9. モバイルでダウンロードされたJavaScriptの総ダウンロード数の分布。
+
棒グラフは、p10パーセンタイルではファーストパーティとサードパーティのリクエストでそれぞれ0/17バイトの JavaScriptがモバイルでダウンロードされていることを示していますが、p25では6/54、p50では83/217、p75では189/477、p90では380/827です。
+
図9. モバイルでダウンロードされたJavaScriptの総ダウンロード数の分布。
中央値では、モバイルとデスクトップの両方で、開発者が作成したファーストパーティのコードよりもサードパーティのコードの方が89%多く使用されています。これは、サードパーティのコードが肥大化の最大の要因の1つであることを明確に示しています。サードパーティの影響についての詳細は、["サードパーティ"](./third-parties)の章を参照してください。 @@ -148,8 +148,8 @@ JavaScriptのリソースを圧縮しているサイトはどれくらいある 図10. JavaScript リソースをgzipまたはbrotliで圧縮しているサイトの割合。 -
バーチャートを見ると、デスクトップとモバイルでそれぞれJavaScriptリソースの67%/65%がgzipで圧縮されており、15%/14%がBrotliで圧縮されていることがわかります。
-
図10. JavaScript リソースをgzipまたはbrotliで圧縮しているサイトの割合。
+
バーチャートを見ると、デスクトップとモバイルでそれぞれJavaScriptリソースの67%/65%がgzipで圧縮されており、15%/14%がBrotliで圧縮されていることがわかります。
+
図10. JavaScript リソースをgzipまたはbrotliで圧縮しているサイトの割合。
大多数のサイトではJavaScriptのリソースを圧縮しています。Gzipエンコーディングはサイトの〜64-67%で、Brotliは〜14%で使用されています。圧縮率はデスクトップとモバイルの両方でほぼ同じです。 @@ -161,7 +161,7 @@ JavaScriptのリソースを圧縮しているサイトはどれくらいある オープンソースコード、または誰でもアクセス、閲覧、修正が可能な寛容なライセンスを持つコード。小さなライブラリから、[Chromium](https://www.chromium.org/Home)や[Firefox](https://www.openhub.net/p/firefox)のようなブラウザ全体に至るまで、オープンソースコードはウェブ開発の世界で重要な役割を果たしています。JavaScriptの文脈では、開発者はオープンソースのツールに依存して、あらゆるタイプの機能をWebページに組み込んでいます。開発者が小さなユーティリティライブラリを使用するか、アプリケーション全体のアーキテクチャを決定する大規模なフレームワークを使用するかにかかわらずオープンソースのパッケージに依存することで、機能開発をより簡単かつ迅速にできます。では、どのJavaScriptオープンソースライブラリが最もよく使われているのでしょうか?
- +
@@ -277,7 +277,7 @@ JavaScriptのリソースを圧縮しているサイトはどれくらいある
ライブラリ
-
図11. デスクトップとモバイルでのトップ JavaScript ライブラリ
+
図11. デスクトップとモバイルでのトップ JavaScript ライブラリ
これまでに作成された中で最も人気のあるJavaScriptライブラリである[jQuery](https://jquery.com/)は、デスクトップページの85.03%、モバイルページの83.46%で使用されています。[Fetch](https://developer.mozilla.org/ja/docs/Web/API/Fetch_API)や[querySelector](https://developer.mozilla.org/ja/docs/Web/API/Document/querySelector)など、多くのブラウザAPIやメソッドの出現により、ライブラリが提供する機能の多くがネイティブ形式に標準化されました。jQueryの人気は衰退しているように見えるかもしれませんが、なぜ今でもウェブの大部分で使われているのでしょうか? @@ -299,14 +299,14 @@ JavaScriptのリソースを圧縮しているサイトはどれくらいある 図12. デスクトップで最もよく使われるフレームワーク -
Reactを使用しているサイトは4.6%、AngularJSを使用しているサイトは2.0%、Backbone.jsを使用しているサイトは1.8%、Vue.jsを使用しているサイトは0.8%、Knockout.jsを使用しているサイトは0.4%、Zone.jsを使用しているサイトは0.3%、Angularを使用しているサイトは0.3%、AMPを使用しているサイトは0.1%、Ember.jsを使用しているサイトは0.1%という棒グラフになっています。
-
図12. デスクトップで最もよく使われるフレームワーク
+
Reactを使用しているサイトは4.6%、AngularJSを使用しているサイトは2.0%、Backbone.jsを使用しているサイトは1.8%、Vue.jsを使用しているサイトは0.8%、Knockout.jsを使用しているサイトは0.4%、Zone.jsを使用しているサイトは0.3%、Angularを使用しているサイトは0.3%、AMPを使用しているサイトは0.1%、Ember.jsを使用しているサイトは0.1%という棒グラフになっています。
+
図12. デスクトップで最もよく使われるフレームワーク
ここでは人気のあるフレームワークのサブセットのみを分析していますが、これらのフレームワークはすべて、これら2つのアプローチのいずれかに従っていることに注意することが重要です。 -- [モデルビューコントローラ](https://developer.chrome.com/apps/app_frameworks)(またはモデルビュービューモデル)アーキテクチャー -- コンポーネントベースアーキテクチャ +- [モデルビューコントローラ](https://developer.chrome.com/apps/app_frameworks)(またはモデルビュービューモデル)アーキテクチャー +- コンポーネントベースアーキテクチャ コンポーネントベースモデルへの移行が進んでいるとはいえ、MVCパラダイムを踏襲した古いフレームワーク([AngularJS](https://angularjs.org/)、[Backbone.js](https://backbonejs.org/)、[Ember](https://emberjs.com/))は、いまだに何千ページにもわたって使われています。しかし、[React](https://reactjs.org/)、[Vue](https://vuejs.org/)、[Angular](https://angular.io/)はコンポーネントベースのフレームワークが主流です([Zone.js](https://github.com/angular/zone.js)は現在Angular coreの一部となっているパッケージです)。 @@ -326,8 +326,8 @@ JavaScriptのリソースを圧縮しているサイトはどれくらいある 図13. type=moduleを利用しているサイトの割合。 -
デスクトップでは0.6%のサイトが「type=module」を使用しており、モバイルでは0.8%のサイトが使用していることを示す棒グラフです。
-
図13. type=moduleを利用しているサイトの割合。
+
デスクトップでは0.6%のサイトが「type=module」を使用しており、モバイルでは0.8%のサイトが使用していることを示す棒グラフです。
+
図13. type=moduleを利用しているサイトの割合。
ブラウザレベルでのモジュールのサポートはまだ比較的新しく、ここでの数字は、現在スクリプトに`type="module"`を使用しているサイトが非常に少ないことを示しています。多くのサイトでは、コードベース内でモジュールを定義するためにモジュールローダー(全デスクトップサイトの2.37%が[RequireJS](https://github.com/requirejs/requirejs)を使用しています)やバンドラー([webpack](https://webpack.js.org/)を使用しています)にまだ依存しています。 @@ -344,8 +344,8 @@ JavaScriptのリソースを圧縮しているサイトはどれくらいある 図14. nomoduleを使用しているサイトの割合。 -
デスクトップでは0.8%のサイトが「nomobule」を利用しており、モバイルでは0.5%のサイトが利用していることを示す棒グラフ。
-
図14. nomoduleを使用しているサイトの割合。
+
デスクトップでは0.8%のサイトが「nomobule」を利用しており、モバイルでは0.5%のサイトが利用していることを示す棒グラフ。
+
図14. nomoduleを使用しているサイトの割合。
同様に、スクリプトに`nomodule`属性を使用しているサイトはほとんどありません(0.50%-0.80%)。 @@ -363,8 +363,8 @@ JavaScriptのリソースを圧縮しているサイトはどれくらいある 図15. スクリプトにrel=preloadを使用しているサイトの割合。 -
バーチャートを見ると、デスクトップでは14%のサイトがスクリプトに'rel=preload'を使用しており、モバイルでは15%のサイトがスクリプトにrel=preloadを使用していることがわかります。
-
図15. スクリプトにrel=preloadを使用しているサイトの割合。
+
バーチャートを見ると、デスクトップでは14%のサイトがスクリプトに'rel=preload'を使用しており、モバイルでは15%のサイトがスクリプトにrel=preloadを使用していることがわかります。
+
図15. スクリプトにrel=preloadを使用しているサイトの割合。
HTTP Archiveで測定したすべてのサイトで、デスクトップサイトの14.33%、モバイルサイトの14.84%が``をページ上のスクリプトに使用しています。 @@ -375,8 +375,8 @@ HTTP Archiveで測定したすべてのサイトで、デスクトップサイ 図16. スクリプトにrel=prefetchを使用しているサイトの割合。 -
デスクトップでは0.08%のサイトが「rel=prefetch」を使用しており、モバイルでは0.08%のサイトが使用していることを示す棒グラフ。
-
図16. スクリプトにrel=prefetchを使用しているサイトの割合。
+
デスクトップでは0.08%のサイトが「rel=prefetch」を使用しており、モバイルでは0.08%のサイトが使用していることを示す棒グラフ。
+
図16. スクリプトにrel=prefetchを使用しているサイトの割合。
モバイルとデスクトップの両方で、0.08%のページがスクリプトのいずれかでプリフェッチを利用しています。 @@ -400,8 +400,8 @@ HTTP Archiveを使用すると、サポートされている(あるいはこ 図17. 新しいJavaScript APIの利用法 -
バーチャートを見ると、デスクトップとモバイルのサイトの25.5%/36.2%がWeakMap、6.1%/17.2%がWeakSet、3.9%/14.0%がIntl、3.9%/4.4%がProxy、0.4%/0.4%がAtomics、0.2%/0.2%がSharedArrayBufferを使用していることがわかります。
-
図17. 新しいJavaScript APIの利用法
+
バーチャートを見ると、デスクトップとモバイルのサイトの25.5%/36.2%がWeakMap、6.1%/17.2%がWeakSet、3.9%/14.0%がIntl、3.9%/4.4%がProxy、0.4%/0.4%がAtomics、0.2%/0.2%がSharedArrayBufferを使用していることがわかります。
+
図17. 新しいJavaScript APIの利用法
Atomics(0.38%)とSharedArrayBuffer(0.20%)は、使用されているページが少ないので、このチャートではほとんど見えません。 @@ -420,8 +420,8 @@ Atomics(0.38%)とSharedArrayBuffer(0.20%)は、使用されているペー 図18. ソースマップを使用しているサイトの割合。 -
デスクトップサイトの18%、モバイルサイトの17%がソースマップを使用していることを示す棒グラフ。
-
図18. ソースマップを使用しているサイトの割合。
+
デスクトップサイトの18%、モバイルサイトの17%がソースマップを使用していることを示す棒グラフ。
+
図18. ソースマップを使用しているサイトの割合。
デスクトップページでもモバイルページでも、結果はほぼ同じです。17~18%は、ページ上に少なくとも1つのスクリプトのソースマップを含んでいます(`sourceMappingURL`を持つファーストパーティスクリプトとして検出されます)。 diff --git a/src/content/ja/2019/resource-hints.md b/src/content/ja/2019/resource-hints.md index f6d8ffa87ee..20284d9ffb0 100644 --- a/src/content/ja/2019/resource-hints.md +++ b/src/content/ja/2019/resource-hints.md @@ -19,9 +19,9 @@ last_updated: 2020-05-14T00:00:00.000Z [例](https://youtu.be/YJGCZCaIZkQ?t=1956)は、リソースヒントの結果としてパフォーマンスが向上しています。 -* Jabongは、重要なスクリプトをプリロードすることで、対話までの時間を1.5秒短縮しました。 -* Barefoot Wineは、目に見えるリンクを先読みすることで、将来のページの対話までの時間を2.7秒短縮しました。 -* Chrome.comは、クリティカルなオリジンに事前接続することで、待ち時間を0.7秒短縮しました。 +* Jabongは、重要なスクリプトをプリロードすることで、対話までの時間を1.5秒短縮しました。 +* Barefoot Wineは、目に見えるリンクを先読みすることで、将来のページの対話までの時間を2.7秒短縮しました。 +* Chrome.comは、クリティカルなオリジンに事前接続することで、待ち時間を0.7秒短縮しました。 今日、ほとんどのブラウザでサポートされているリソースヒントには、4つの独立したものがあります。`dns-prefetch`, `preconnect`, `preload`, `prefetch` です。 diff --git a/src/content/ja/2019/security.md b/src/content/ja/2019/security.md index 8b0c7d11da4..aab611ff474 100644 --- a/src/content/ja/2019/security.md +++ b/src/content/ja/2019/security.md @@ -272,10 +272,10 @@ Content-Security-Policy: upgrade-insecure-requests; default-src https: | `no-referrer-when-downgrade` | 39.16% | 41.52% | | `strict-origin-when-cross-origin` | 39.16% | 22.17% | | `unsafe-url` | 22.17% | 22.17% | -| `same-origin ` | 7.97% | 7.97% | +| `same-origin` | 7.97% | 7.97% | | `origin-when-cross-origin` | 6.76% | 6.44% | | `no-referrer` | 5.65% | 5.38% | -| `strict-origin ` | 4.35% | 4.14% | +| `strict-origin` | 4.35% | 4.14% | | `origin` | 3.63% | 3.23% |
図11. `Referrer-Policy` 設定オプションの使用法。
diff --git a/src/static/css/2019.css b/src/static/css/2019.css index b444c134aad..f903a94c784 100644 --- a/src/static/css/2019.css +++ b/src/static/css/2019.css @@ -5,11 +5,12 @@ font-style: italic; font-weight: 400; font-display: swap; - src: local('Lato Italic'), - local('Lato-Italic'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2) */ - url('/static/fonts/Lato-Italic-ext.woff2') - format('woff2'); + src: + local('Lato Italic'), + local('Lato-Italic'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6u8w4BMUTPHjxsAUi-qNiXg7eU0.woff2) */ + url('/static/fonts/Lato-Italic-ext.woff2') + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @@ -18,11 +19,12 @@ font-style: italic; font-weight: 400; font-display: swap; - src: local('Lato Italic'), - local('Lato-Italic'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6u8w4BMUTPHjxsAXC-qNiXg7Q.woff2) */ - url('/static/fonts/Lato-Italic.woff2') - format('woff2'); + src: + local('Lato Italic'), + local('Lato-Italic'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6u8w4BMUTPHjxsAXC-qNiXg7Q.woff2) */ + url('/static/fonts/Lato-Italic.woff2') + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @@ -31,11 +33,12 @@ font-style: italic; font-weight: 700; font-display: swap; - src: local('Lato Bold Italic'), - local('Lato-BoldItalic'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6u_w4BMUTPHjxsI5wq_FQftx9897sxZ.woff2) */ - url('/static/fonts/Lato-BoldItalic-ext.woff2') - format('woff2'); + src: + local('Lato Bold Italic'), + local('Lato-BoldItalic'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6u_w4BMUTPHjxsI5wq_FQftx9897sxZ.woff2) */ + url('/static/fonts/Lato-BoldItalic-ext.woff2') + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @@ -44,11 +47,12 @@ font-style: italic; font-weight: 700; font-display: swap; - src: local('Lato Bold Italic'), - local('Lato-BoldItalic'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6u_w4BMUTPHjxsI5wq_Gwftx9897g.woff2) */ - url('/static/fonts/Lato-BoldItalic.woff2') - format('woff2'); + src: + local('Lato Bold Italic'), + local('Lato-BoldItalic'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6u_w4BMUTPHjxsI5wq_Gwftx9897g.woff2) */ + url('/static/fonts/Lato-BoldItalic.woff2') + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @@ -57,11 +61,12 @@ font-style: normal; font-weight: 400; font-display: swap; - src: local('Lato Regular'), - local('Lato-Regular'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjxAwXiWtFCfQ7A.woff2) */ - url('/static/fonts/Lato-Regular-ext.woff2') - format('woff2'); + src: + local('Lato Regular'), + local('Lato-Regular'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjxAwXiWtFCfQ7A.woff2) */ + url('/static/fonts/Lato-Regular-ext.woff2') + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @@ -70,11 +75,12 @@ font-style: normal; font-weight: 400; font-display: swap; - src: local('Lato Regular'), - local('Lato-Regular'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjx4wXiWtFCc.woff2) */ - url('/static/fonts/Lato-Regular.woff2') - format('woff2'); + src: + local('Lato Regular'), + local('Lato-Regular'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6uyw4BMUTPHjx4wXiWtFCc.woff2) */ + url('/static/fonts/Lato-Regular.woff2') + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @@ -83,11 +89,12 @@ font-style: normal; font-weight: 700; font-display: swap; - src: local('Lato Bold'), - local('Lato-Bold'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6u9w4BMUTPHh6UVSwaPGQ3q5d0N7w.woff2) */ - url('/static/fonts/Lato-Bold-ext.woff2') - format('woff2'); + src: + local('Lato Bold'), + local('Lato-Bold'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6u9w4BMUTPHh6UVSwaPGQ3q5d0N7w.woff2) */ + url('/static/fonts/Lato-Bold-ext.woff2') + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @@ -96,11 +103,12 @@ font-style: normal; font-weight: 700; font-display: swap; - src: local('Lato Bold'), - local('Lato-Bold'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2) */ - url('/static/fonts/Lato-Bold.woff2') - format('woff2'); + src: + local('Lato Bold'), + local('Lato-Bold'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2) */ + url('/static/fonts/Lato-Bold.woff2') + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @@ -109,11 +117,12 @@ font-style: normal; font-weight: 900; font-display: swap; - src: local('Lato Black'), - local('Lato-Black'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6u9w4BMUTPHh50XSwaPGQ3q5d0N7w.woff2) */ - url('/static/fonts/Lato-Black-ext.woff2') - format('woff2'); + src: + local('Lato Black'), + local('Lato-Black'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6u9w4BMUTPHh50XSwaPGQ3q5d0N7w.woff2) */ + url('/static/fonts/Lato-Black-ext.woff2') + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @@ -122,11 +131,12 @@ font-style: normal; font-weight: 900; font-display: swap; - src: local('Lato Black'), - local('Lato-Black'), - /* url(https://fonts.gstatic.com/s/lato/v16/S6u9w4BMUTPHh50XSwiPGQ3q5d0.woff2) */ - url('/static/fonts/Lato-Black.woff2') - format('woff2'); + src: + local('Lato Black'), + local('Lato-Black'), + /* url(https://fonts.gstatic.com/s/lato/v16/S6u9w4BMUTPHh50XSwiPGQ3q5d0.woff2) */ + url('/static/fonts/Lato-Black.woff2') + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* devanagari */ @@ -135,11 +145,12 @@ font-style: normal; font-weight: 300; font-display: swap; - src: local('Poppins Light'), - local('Poppins-Light'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLDz8Z11lFd2JQEl8qw.woff2) */ - url('/static/fonts/Poppins-Light-devanagari.woff2') - format('woff2'); + src: + local('Poppins Light'), + local('Poppins-Light'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLDz8Z11lFd2JQEl8qw.woff2) */ + url('/static/fonts/Poppins-Light-devanagari.woff2') + format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB; } /* latin-ext */ @@ -148,11 +159,12 @@ font-style: normal; font-weight: 300; font-display: swap; - src: local('Poppins Light'), - local('Poppins-Light'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLDz8Z1JlFd2JQEl8qw.woff2) */ - url('/static/fonts/Poppins-Light-ext.woff2') - format('woff2'); + src: + local('Poppins Light'), + local('Poppins-Light'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLDz8Z1JlFd2JQEl8qw.woff2) */ + url('/static/fonts/Poppins-Light-ext.woff2') + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @@ -161,11 +173,12 @@ font-style: normal; font-weight: 300; font-display: swap; - src: local('Poppins Light'), - local('Poppins-Light'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLDz8Z1xlFd2JQEk.woff2) */ - url('/static/fonts/Poppins-Light.woff2') - format('woff2'); + src: + local('Poppins Light'), + local('Poppins-Light'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLDz8Z1xlFd2JQEk.woff2) */ + url('/static/fonts/Poppins-Light.woff2') + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* devanagari */ @@ -174,11 +187,12 @@ font-style: normal; font-weight: 400; font-display: swap; - src: local('Poppins Regular'), - local('Poppins-Regular'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiEyp8kv8JHgFVrJJbecnFHGPezSQ.woff2) */ - url('/static/fonts/Poppins-Regular-devanagari.woff2') - format('woff2'); + src: + local('Poppins Regular'), + local('Poppins-Regular'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiEyp8kv8JHgFVrJJbecnFHGPezSQ.woff2) */ + url('/static/fonts/Poppins-Regular-devanagari.woff2') + format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB; } /* latin-ext */ @@ -187,11 +201,12 @@ font-style: normal; font-weight: 400; font-display: swap; - src: local('Poppins Regular'), - local('Poppins-Regular'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiEyp8kv8JHgFVrJJnecnFHGPezSQ.woff2) */ - url('/static/fonts/Poppins-Regular-ext.woff2') - format('woff2'); + src: + local('Poppins Regular'), + local('Poppins-Regular'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiEyp8kv8JHgFVrJJnecnFHGPezSQ.woff2) */ + url('/static/fonts/Poppins-Regular-ext.woff2') + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @@ -200,11 +215,12 @@ font-style: normal; font-weight: 400; font-display: swap; - src: local('Poppins Regular'), - local('Poppins-Regular'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiEyp8kv8JHgFVrJJfecnFHGPc.woff2) */ - url('/static/fonts/Poppins-Regular.woff2') - format('woff2'); + src: + local('Poppins Regular'), + local('Poppins-Regular'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiEyp8kv8JHgFVrJJfecnFHGPc.woff2) */ + url('/static/fonts/Poppins-Regular.woff2') + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* devanagari */ @@ -213,11 +229,12 @@ font-style: normal; font-weight: 700; font-display: swap; - src: local('Poppins Bold'), - local('Poppins-Bold'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLCz7Z11lFd2JQEl8qw.woff2) */ - url('/static/fonts/Poppins-Bold-devanagari.woff2') - format('woff2'); + src: + local('Poppins Bold'), + local('Poppins-Bold'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLCz7Z11lFd2JQEl8qw.woff2) */ + url('/static/fonts/Poppins-Bold-devanagari.woff2') + format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB; } /* latin-ext */ @@ -226,11 +243,12 @@ font-style: normal; font-weight: 700; font-display: swap; - src: local('Poppins Bold'), - local('Poppins-Bold'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLCz7Z1JlFd2JQEl8qw.woff2) */ - url('/static/fonts/Poppins-Bold-ext.woff2') - format('woff2'); + src: + local('Poppins Bold'), + local('Poppins-Bold'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLCz7Z1JlFd2JQEl8qw.woff2) */ + url('/static/fonts/Poppins-Bold-ext.woff2') + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @@ -239,11 +257,12 @@ font-style: normal; font-weight: 700; font-display: swap; - src: local('Poppins Bold'), - local('Poppins-Bold'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLCz7Z1xlFd2JQEk.woff2) */ - url('/static/fonts/Poppins-Bold.woff2') - format('woff2'); + src: + local('Poppins Bold'), + local('Poppins-Bold'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLCz7Z1xlFd2JQEk.woff2) */ + url('/static/fonts/Poppins-Bold.woff2') + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* devanagari */ @@ -252,11 +271,12 @@ font-style: normal; font-weight: 900; font-display: swap; - src: local('Poppins Black'), - local('Poppins-Black'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLBT5Z11lFd2JQEl8qw.woff2) */ - url('/static/fonts/Poppins-Black-devanagari.woff2') - format('woff2'); + src: + local('Poppins Black'), + local('Poppins-Black'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLBT5Z11lFd2JQEl8qw.woff2) */ + url('/static/fonts/Poppins-Black-devanagari.woff2') + format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB; } /* latin-ext */ @@ -265,11 +285,12 @@ font-style: normal; font-weight: 900; font-display: swap; - src: local('Poppins Black'), - local('Poppins-Black'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLBT5Z1JlFd2JQEl8qw.woff2) */ - url('/static/fonts/Poppins-Black-ext.woff2') - format('woff2'); + src: + local('Poppins Black'), + local('Poppins-Black'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLBT5Z1JlFd2JQEl8qw.woff2) */ + url('/static/fonts/Poppins-Black-ext.woff2') + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @@ -278,11 +299,12 @@ font-style: normal; font-weight: 900; font-display: swap; - src: local('Poppins Black'), - local('Poppins-Black'), - /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLBT5Z1xlFd2JQEk.woff2) */ - url('/static/fonts/Poppins-Black.woff2') - format('woff2'); + src: + local('Poppins Black'), + local('Poppins-Black'), + /* url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLBT5Z1xlFd2JQEk.woff2) */ + url('/static/fonts/Poppins-Black.woff2') + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -304,7 +326,7 @@ * Margins and paddings should be considered if the need to be relative (em or rem) * or happy not to scale with fonts and want set about in px. * If scaling, then in general top and bottom should scale with element (em), and - * left and right with root element (rem) to have consistent alignment (see + * left and right with root element (rem) to have consistent alignment (see * https://zellwk.com/blog/rem-vs-em/#rems-or-ems%3F for why). * So we set margin like this: * @@ -320,7 +342,7 @@ body { font-family: 'Lato', sans-serif; - color: #1A2B49; + color: #1a2b49; margin: 0; font-weight: inherit; -webkit-font-smoothing: antialiased; @@ -395,7 +417,7 @@ img { text-transform: uppercase; color: red; vertical-align: super; - font-size: .5em; + font-size: 0.5em; } .title-lg { @@ -427,34 +449,36 @@ h2.header { font-size: 25px; font-size: 1.5625rem; margin: 14px; - margin: 0.56em 0.875rem + margin: 0.56em 0.875rem; } .btn { - border: 1px solid #1A2B49; + border: 1px solid #1a2b49; border-radius: 50px; padding: 15px 30px; padding: 1.07em 1.875rem; - background: #1A2B49; - color: #FFFFFF; + background: #1a2b49; + color: #fff; font-size: 14px; font-size: 0.875rem; text-decoration: none; } + .btn:hover, .btn:focus, .alt.btn { - background: #FFFFFF; - color: #1A2B49; + background: #fff; + color: #1a2b49; } + .alt.btn:hover, .alt.btn:focus { - background: #1A2B49; - color: #FFFFFF; + background: #1a2b49; + color: #fff; } .alt-bg { - background-color: #5C687D; + background-color: #5c687d; color: #f2f2f2; } @@ -476,7 +500,7 @@ h2.header { position: relative; z-index: 1; line-height: 1; - overflow: hidden; + overflow: hidden; } .navigation-logo .line-group::after { @@ -485,11 +509,11 @@ h2.header { height: 1px; width: 100%; background-color: #f7f779; - bottom: calc(.4em - 1px); - margin-inline-start: .5em; /* cover both rtl and ltr scenarios */ + bottom: calc(0.4em - 1px); + margin-inline-start: 0.5em; /* cover both rtl and ltr scenarios */ } -.navigation-logo .wa { +.navigation-logo .wa { font-weight: 600; letter-spacing: 5px; font-size: 1.3em; @@ -498,30 +522,33 @@ h2.header { } .navigation-logo .pre, -.navigation-logo .ha { - font-size: .8em; +.navigation-logo .ha { + font-size: 0.8em; letter-spacing: 2px; } header.alt-bg a:hover, footer.alt-bg a:hover, header.alt-bg a:focus, footer.alt-bg a:focus { - color: #F7F779; + color: #f7f779; } + .alt-bg .btn { - border-color: #F7F779; - background-color: #F7F779; - color: #1A2B49; + border-color: #f7f779; + background-color: #f7f779; + color: #1a2b49; } + .alt-bg .btn:hover, .alt-bg .btn:focus, .alt-bg .alt.btn { background-color: transparent; - color: #F7F779; + color: #f7f779; } + .alt-bg .alt.btn:hover, .alt-bg .alt.btn:focus { - background-color: #F7F779; - color: #1A2B49; + background-color: #f7f779; + color: #1a2b49; } .top-header, footer { @@ -560,12 +587,14 @@ header nav { header nav > ul > li > * { margin-right: 50px; } -header nav > ul > li:last-child > * { + +header nav > ul > li:last-child > * { margin-right: 0; } + nav a { text-decoration: none; - color: #F2F2F2; + color: #f2f2f2; } header .cta { @@ -586,29 +615,29 @@ header .cta { .language-switcher:hover, .year-switcher:hover { - color: #F7F779; + color: #f7f779; } .language-switcher::after, .year-switcher::after { content: ""; position: absolute; - pointer-events: none; + pointer-events: none; border-style: solid; border-width: 2px 2px 0 0; border-color: currentColor; - height: .4em; - width: .4em; + height: 0.4em; + width: 0.4em; top: 50%; - margin-top: -.4em; - /* - 22px is a magic number + margin-top: -0.4em; + /* + 22px is a magic number equal to the select right computed padding + 2px total sides border */ right: 22px; -webkit-transform: rotate(135deg); -ms-transform: rotate(135deg); - transform: rotate(135deg) + transform: rotate(135deg); } .language-switcher select, @@ -621,7 +650,7 @@ header .cta { cursor: pointer; -webkit-appearance: none; -moz-appearance: none; - appearance: none; + appearance: none; min-width: 100px; } @@ -632,7 +661,7 @@ header .cta { .language-switcher option, .year-switcher option { - color: #1A2B49; + color: #1a2b49; background-color: white; } @@ -640,8 +669,8 @@ header .cta { .year-switcher:focus-within, .language-switcher select:focus, .year-switcher select:focus { - border-color: #F7F779; - color: #F7F779; + border-color: #f7f779; + color: #f7f779; } .not-translated { @@ -656,7 +685,7 @@ header .cta { } .main { - margin: 0px auto; + margin: 0 auto; font-size: 17px; font-size: 1.0625rem; } @@ -669,6 +698,7 @@ header .cta { h2, h3, h4 { margin-top: 2em; } + h2 code, h3 code, h4 code { @@ -702,7 +732,7 @@ blockquote::before { position: absolute; top: -4rem; left: -7rem; - opacity: .05; + opacity: 0.05; font-size: 20rem; font-family: 'Courier New', Courier, monospace; line-height: 1; @@ -727,15 +757,18 @@ footer .home-logo { justify-content: start; align-items: center; } + footer .nav-items { grid-area: nav-items; display: flex; justify-content: flex-end; align-items: center; } + footer .mobile-ha-social-media { display: none; } + footer .ha-logo { grid-area: ha-logo; display: flex; @@ -743,32 +776,39 @@ footer .ha-logo { align-items: center; color: currentColor; } + footer .nav-items ul li > * { margin-left: 50px; } + footer .language-switcher { grid-area: language-switcher; } + footer .copyright { grid-area: copyright; display: block; align-items: center; } + footer .social-media { grid-area: social-media; display: flex; align-items: center; justify-content: flex-end; } + footer ul { margin-block-start: 0; margin-block-end: 0; } + footer hr { grid-area: hr; width: 100%; - margin: 40px 0px 20px 0; + margin: 40px 0 20px 0; } + footer hr:last-of-type { grid-area: hr-last; display: none; @@ -778,8 +818,9 @@ p.copyright { margin: 0; font-size: 16px; font-size: 1rem; - color: #F2F2F2; + color: #f2f2f2; } + p.copyright a { color: white; } @@ -800,32 +841,35 @@ p.copyright a { color: #8c99a3; } - @media (max-width: 900px) and (min-width: 601px) { - /* Header */ .top-header, footer { position: relative; padding-top: 30px; padding-bottom: 30px; } + header nav:first-of-type, header .cta { display: none; } + header nav > ul > li > * { margin: 0; } + header nav > ul > li > a { margin-bottom: 50px; margin-bottom: 3.125rem; font-size: 16px; font-size: 1rem; - line-height: 1.4em + line-height: 1.4em; } + header nav > ul > li:last-child { margin: 0; } + header .social-media li { display: inline; } @@ -841,27 +885,31 @@ p.copyright a { grid-template-columns: 3fr 1fr 1fr 120px 0 0; grid-template-rows: 60px auto auto; } + footer .nav-items { grid-area: nav-items; display: flex; justify-content: center; align-items: center; } + footer .nav-items ul { display: flex; flex-direction: column; justify-content: center; align-items: center; } + footer .nav-items ul li > * { - margin-left: 0; - margin: 20px 0px; + margin: 20px 0; font-size: 16px; font-size: 1rem; } + footer hr { - margin: 20px 0px; + margin: 20px 0; } + footer hr:last-of-type { display: block; } @@ -886,8 +934,7 @@ p.copyright a { position: absolute; top: -40px; top: -2.35em; - left: 0px; - color: white; + left: 0; border-right: 1px solid white; border-bottom: 1px solid white; border-bottom-right-radius: 8px; @@ -900,11 +947,11 @@ p.copyright a { #skiptocontent a:focus { position: absolute; - left: 0px; - top: 0px; + left: 0; + top: 0; outline-color: transparent; - -webkit-transition: top .1s ease-in; - transition: top .1s ease-in; + -webkit-transition: top 0.1s ease-in; + transition: top 0.1s ease-in; } /* Mobile View */ @@ -917,11 +964,11 @@ p.copyright a { .title-lg { font-size: 40px; font-size: 2.5rem; - font-size: min(2.5rem,15vw); /* Cap max font size on mobile, if possible. Allows 200% font-size. */ + font-size: min(2.5rem, 15vw); /* Cap max font size on mobile, if possible. Allows 200% font-size. */ } h2 { - font-size: min(1.5rem,12vw); /* Cap max font size on mobile, if possible. Allows 200% font-size. */ + font-size: min(1.5rem, 12vw); /* Cap max font size on mobile, if possible. Allows 200% font-size. */ } /* Header */ @@ -930,26 +977,32 @@ p.copyright a { padding-top: 30px; padding-bottom: 30px; } + header nav:first-of-type, header .cta { display: none; } + .navigation-logo { min-width: auto; max-width: 75vw; } + header nav > ul > li > * { margin: 0; } + header nav > ul > li > a { margin-bottom: 50px; font-size: 16px; font-size: 1rem; - line-height: 1.4em + line-height: 1.4em; } + header nav > ul > li:last-child { margin: 0; } + header .social-media li { display: inline; } @@ -970,48 +1023,55 @@ p.copyright a { grid-template-columns: 1fr; grid-template-rows: auto; } + footer .home-logo { grid-area: home-logo; - margin: 20px 0px; + margin: 20px 0; } + footer .mobile-ha-social-media { display: grid; grid-area: ha-social-media; - grid-template-areas: - 'ha-logo social-media'; + grid-template-areas: 'ha-logo social-media'; } + footer .ha-logo { grid-area: ha-logo; display: flex; justify-content: flex-start; align-items: center; - margin: 20px 0px; + margin: 20px 0; } + footer .nav-items { grid-area: nav-items; display: flex; justify-content: center; align-items: center; } + footer .nav-items ul { display: flex; flex-direction: column; justify-content: center; align-items: center; } + footer .nav-items ul li > * { - margin-left: 0; - margin: 20px 0px; + margin: 20px 0; font-size: 16px; font-size: 1rem; } + footer .language-switcher { grid-area: language-switcher; } + p.copyright { font-size: 12px; font-size: 0.75rem; } + footer .copyright { grid-area: copyright; display: block; @@ -1019,12 +1079,15 @@ p.copyright a { align-items: center; margin-top: 20px; } + footer .social-media { grid-area: social-media; } + footer hr { - margin: 20px 0px; + margin: 20px 0; } + footer hr:last-of-type { display: block; } @@ -1038,14 +1101,14 @@ p.copyright a { #menu { display: block; } + .menu { position: absolute; display: none; flex-direction: column; top: 100%; - /* overcome the parent container's 20px side padding */ - left: -20px; - right: -20px; + left: -20px; /* overcome the parent container's 20px side padding */ + right: -20px; /* overcome the parent container's 20px side padding */ border-top: 1px solid rgba(242, 242, 242, 0.2); padding: 60px 30px 30px; background-color: #677486; @@ -1061,11 +1124,11 @@ p.copyright a { padding: 5px; height: 40px; width: 37px; - color: #f2f2f2; + color: #f2f2f2; } .menu-btn:hover { - color: #f7f779; + color: #f7f779; } .menu-btn__bar { @@ -1074,7 +1137,7 @@ p.copyright a { height: 2px; background-color: currentColor; border-radius: 2px; - transition: 0.15s cubic-bezier(0.75, -0.55, 0.25, 1.55) + transition: 0.15s cubic-bezier(0.75, -0.55, 0.25, 1.55); } .menu-btn__bar + .menu-btn__bar { @@ -1088,7 +1151,7 @@ p.copyright a { .menu-btn--active .menu-btn__bar { margin: 0; - position: absolute; + position: absolute; } .menu-btn--active .menu-btn__bar:nth-child(1) { @@ -1097,12 +1160,12 @@ p.copyright a { } .menu-btn--active .menu-btn__bar:nth-child(2) { - opacity: 0 + opacity: 0; } .menu-btn--active .menu-btn__bar:nth-child(3) { -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); + transform: rotate(-45deg); } .menu-open .menu { diff --git a/src/static/css/ebook.css b/src/static/css/ebook.css index 1cd42cd1a57..6734aba00e6 100644 --- a/src/static/css/ebook.css +++ b/src/static/css/ebook.css @@ -3,8 +3,8 @@ } #title { - background: #5C687D; - background: transparent linear-gradient(#5C687D 70%, transparent 30%); + background: #5c687d; + background: transparent linear-gradient(#5c687d 70%, transparent 30%); /* background: transparent url(/static/images/intro-background-fit.svg) bottom left / 100% 100% no-repeat; */ background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOTIwIiBoZWlnaHQ9IjEyNTAiIHZpZXdCb3g9IjAgMCAxOTIwIDEyNTAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPg0KICA8ZGVmcz4NCiAgICA8c3R5bGU+DQogICAgICBzdmd7YmFja2dyb3VuZDojZmZmfQ0KICAgICAgLmNscy0xe2ZpbGw6I2E4Y2FiYTtmaWxsLXJ1bGU6ZXZlbm9kZDtvcGFjaXR5Oi4wNX0NCiAgICA8L3N0eWxlPg0KICA8L2RlZnM+DQogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTS0yMzEgODloMjA4OHY2NTFsLTIwODggMzYwVjg5eiIvPg0KICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0tNDcwIDIzOWgyMDg4djY1MWwtMjA4OCAzNjBWMjM5eiIvPg0KICA8cGF0aCBkPSJNLTE0NC0xOWgyMDg4djY1MUwtMTQ0IDk5MlYtMTl6IiBmaWxsPSIjMWEyYjQ5IiBvcGFjaXR5PSIuNzUiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPg0KICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0tNDcwLTgzaDIwODh2NjUxTC00NzAgOTI4Vi04M3oiLz4NCiAgPHBhdGggZD0iTS0yMzItNDhoMjA4OHY2NTFMLTIzMiA5NjNWLTQ4eiIgZmlsbD0iI2YyZjJmMiIgb3BhY2l0eT0iLjA1IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz4NCjwvc3ZnPg0K); background-position: bottom left; @@ -15,7 +15,7 @@ .intro-year { margin: 0; width: auto; - color: #F7F779; + color: #f7f779; font-size: 160px; font-size: 10rem; line-height: 100%; @@ -52,12 +52,12 @@ } .byline { - font-style: italic; + font-style: italic; } .byline.authors { - font-weight: bold; - border-bottom: none; + font-weight: bold; + border-bottom: none; } .table-wrap-container { @@ -106,7 +106,6 @@ tbody tr:nth-child(even) { width: 80px; } - .contributors { padding: 0; columns: 2; @@ -130,7 +129,7 @@ tbody tr:nth-child(even) { margin-right: 10px; width: 50px; height: auto; - transition-duration: .3s; + transition-duration: 0.3s; float: left; } @@ -149,12 +148,15 @@ tbody tr:nth-child(even) { font-size: 0.875rem; color: #757575; } + .contributor-team::after { content: ', '; } + .contributor-team:last-child::after { content: ''; } + .social-icon { height: 15px; width: 15px; @@ -178,7 +180,9 @@ tbody tr:nth-child(even) { white-space: pre-wrap; } -section.chapter {prince-pdf-tag-type: Art;} +section.chapter { + prince-pdf-tag-type: Art; +} .fn { display: none; @@ -198,7 +202,7 @@ section.chapter {prince-pdf-tag-type: Art;} @top-left { width: 100%; margin: 30pt 0 10pt 0; - border-bottom: .50pt solid #666; + border-bottom: 0.5pt solid #666; color: #333; font-family: 'Poppins', sans-serif; } @@ -213,30 +217,28 @@ section.chapter {prince-pdf-tag-type: Art;} @bottom-left { width: 100%; margin: 10pt 0 30pt 0; - border-top: .50pt solid #666; + border-top: 0.5pt solid #666; color: #333; font-family: 'Poppins', sans-serif; } - @bottom-right { + @bottom-right { width: 100%; margin: 10pt 0 30pt 0; - border-top: .25pt solid #666; + border-top: 0.25pt solid #666; color: #333; font-family: 'Poppins', sans-serif; } - } @page :blank { - @top-left { content: ''; } + @top-right { content: ''; } - } .no-header-or-footer { @@ -244,22 +246,23 @@ section.chapter {prince-pdf-tag-type: Art;} } @page no-header-or-footer { - @top-left { content: ''; } + @top-right { content: ''; } + @bottom-left { content: ''; border: none; } + @bottom-right { content: ''; border: none; } - } #toc, #foreword { @@ -267,9 +270,8 @@ section.chapter {prince-pdf-tag-type: Art;} } @page :first { - - background: #5C687D; - background: transparent linear-gradient(#5C687D 70%, transparent 30%); + background: #5c687d; + background: transparent linear-gradient(#5c687d 70%, transparent 30%); /* background: transparent url(/static/images/intro-background-fit.svg) bottom left / 100% 100% no-repeat; */ background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOTIwIiBoZWlnaHQ9IjEyNTAiIHZpZXdCb3g9IjAgMCAxOTIwIDEyNTAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPg0KICA8ZGVmcz4NCiAgICA8c3R5bGU+DQogICAgICBzdmd7YmFja2dyb3VuZDojZmZmfQ0KICAgICAgLmNscy0xe2ZpbGw6I2E4Y2FiYTtmaWxsLXJ1bGU6ZXZlbm9kZDtvcGFjaXR5Oi4wNX0NCiAgICA8L3N0eWxlPg0KICA8L2RlZnM+DQogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTS0yMzEgODloMjA4OHY2NTFsLTIwODggMzYwVjg5eiIvPg0KICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0tNDcwIDIzOWgyMDg4djY1MWwtMjA4OCAzNjBWMjM5eiIvPg0KICA8cGF0aCBkPSJNLTE0NC0xOWgyMDg4djY1MUwtMTQ0IDk5MlYtMTl6IiBmaWxsPSIjMWEyYjQ5IiBvcGFjaXR5PSIuNzUiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPg0KICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0tNDcwLTgzaDIwODh2NjUxTC00NzAgOTI4Vi04M3oiLz4NCiAgPHBhdGggZD0iTS0yMzItNDhoMjA4OHY2NTFMLTIzMiA5NjNWLTQ4eiIgZmlsbD0iI2YyZjJmMiIgb3BhY2l0eT0iLjA1IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz4NCjwvc3ZnPg0K); background-position: bottom left; @@ -280,22 +282,23 @@ section.chapter {prince-pdf-tag-type: Art;} content: ''; border-bottom: none; } + @top-right { content: ''; } + @bottom-left { content: ''; border: none; } + @bottom-right { content: ''; border: none; } - } @media print { - #title { background: none; } @@ -319,7 +322,7 @@ section.chapter {prince-pdf-tag-type: Art;} .content > section { page-break-after: always; } - + #toc a::after { content: leader('.') target-counter(attr(href), page); } @@ -337,7 +340,7 @@ section.chapter {prince-pdf-tag-type: Art;} } figure { - margin: 0; + margin: 0; } figure, @@ -380,10 +383,10 @@ section.chapter {prince-pdf-tag-type: Art;} h1, h2, h3, h4, h5 { font-weight: bold; page-break-after: avoid; - page-break-inside:avoid; + page-break-inside: avoid; } - - h1+p, h2+p, h3+p { + + h1 + p, h2 + p, h3 + p { page-break-before: avoid; } @@ -426,4 +429,4 @@ section.chapter {prince-pdf-tag-type: Art;} .content section.authors li *:first-child { flex: 0 0 76px; -} \ No newline at end of file +} diff --git a/src/static/css/index.css b/src/static/css/index.css index 48801ba71cd..5c8a3ccd32f 100644 --- a/src/static/css/index.css +++ b/src/static/css/index.css @@ -4,8 +4,8 @@ body { } header.alt-bg { - background: #5C687D; - background: transparent linear-gradient(#5C687D 70%, transparent 30%); + background: #5c687d; + background: transparent linear-gradient(#5c687d 70%, transparent 30%); /* background: transparent url(/static/images/intro-background-fit.svg) bottom left / 100% 100% no-repeat; */ background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOTIwIiBoZWlnaHQ9IjEyNTAiIHZpZXdCb3g9IjAgMCAxOTIwIDEyNTAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPg0KICA8ZGVmcz4NCiAgICA8c3R5bGU+DQogICAgICBzdmd7YmFja2dyb3VuZDojZmZmfQ0KICAgICAgLmNscy0xe2ZpbGw6I2E4Y2FiYTtmaWxsLXJ1bGU6ZXZlbm9kZDtvcGFjaXR5Oi4wNX0NCiAgICA8L3N0eWxlPg0KICA8L2RlZnM+DQogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTS0yMzEgODloMjA4OHY2NTFsLTIwODggMzYwVjg5eiIvPg0KICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0tNDcwIDIzOWgyMDg4djY1MWwtMjA4OCAzNjBWMjM5eiIvPg0KICA8cGF0aCBkPSJNLTE0NC0xOWgyMDg4djY1MUwtMTQ0IDk5MlYtMTl6IiBmaWxsPSIjMWEyYjQ5IiBvcGFjaXR5PSIuNzUiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPg0KICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0tNDcwLTgzaDIwODh2NjUxTC00NzAgOTI4Vi04M3oiLz4NCiAgPHBhdGggZD0iTS0yMzItNDhoMjA4OHY2NTFMLTIzMiA5NjNWLTQ4eiIgZmlsbD0iI2YyZjJmMiIgb3BhY2l0eT0iLjA1IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz4NCjwvc3ZnPg0K); background-position: bottom left; @@ -20,14 +20,14 @@ header.alt-bg { /* Add fall back background color in case SVG fails to load so text is still readable */ header::after { content: ""; - background: #5C687D; + background: #5c687d; top: 0; left: 0; bottom: 600px; right: 0; display: block; position: absolute; - z-index: -1; + z-index: -1; } header .container { @@ -50,7 +50,7 @@ header .container { width: 100vw; position: relative; left: 50%; - margin-left: -50vw; + margin-left: -50vw; } #maincontent section { @@ -80,14 +80,13 @@ p { } .intro-container { - color: #FFFFFF; + color: #fff; grid-area: intro; - display: -ms-grid; -ms-grid-row: 1; -ms-grid-columns: 2fr 1fr; + display: -ms-grid; display: grid; - grid-template-areas: - 'intro image'; + grid-template-areas: 'intro image'; justify-content: space-between; padding: 0 60px; } @@ -111,7 +110,7 @@ p { -ms-grid-row: 2; grid-area: image; display: none; - width:100%; + width: 100%; } .intro-image { @@ -124,7 +123,7 @@ p { .intro-image-year-wrapper { -ms-grid-column: 2; grid-area: image; - width:100%; + width: 100%; } .intro-image-year { @@ -145,14 +144,15 @@ p { } .intro .btn { - border-color: #F7F779; - background-color: #F7F779; - color: #1A2B49; + border-color: #f7f779; + background-color: #f7f779; + color: #1a2b49; } + .intro .btn:hover, .intro .btn:focus { background-color: transparent; - color: #F7F779; + color: #f7f779; } /* Featured Chapter */ @@ -242,7 +242,7 @@ p { .people-number { font-family: 'Poppins', sans-serif; - color: #FFFFFF; + color: #fff; font-size: 600px; font-weight: bold; letter-spacing: 50px; @@ -321,17 +321,14 @@ p { max-width: 100%; height: auto; z-index: -1; - background: linear-gradient(180deg, - rgba(0,0,0,0) calc(70% - 1px), - rgb(192, 192, 192) calc(50%), - rgba(0,0,0,0) calc(70% + 1px) - ); + background: linear-gradient(180deg, rgba(0, 0, 0, 0) calc(70% - 1px), rgb(192, 192, 192) calc(50%), rgba(0, 0, 0, 0) calc(70% + 1px)); } @media (max-width: 1280px) and (min-width: 901px) { .people { height: auto; } + .people-number { font-size: 300px; overflow: visible; @@ -340,21 +337,25 @@ p { position: relative; left: 50px; } + .people .character { width: 8vw; height: auto; } + #character-markup { position: absolute; top: auto; right: 10%; bottom: 65%; } + #character-star { position: absolute; bottom: 0; left: 30%; } + #character-hat { position: absolute; bottom: 0; @@ -363,7 +364,6 @@ p { } @media (max-width: 900px) and (min-width: 601px) { - header.alt-bg { padding-bottom: 1800px; padding-bottom: 105.88em; @@ -384,16 +384,18 @@ p { justify-content: center; padding: 40px 60px; } + .intro { margin: 0; width: auto; text-align: center; } + .intro-year { display: block; margin: 0; width: auto; - color: #F7F779; + color: #f7f779; font-size: 190px; line-height: 160px; font-weight: bold; @@ -405,6 +407,7 @@ p { margin-top: 80px; margin-right: -46px; } + .intro-image-year-wrapper { display: none; } @@ -419,8 +422,6 @@ p { .contributors-container { background-image: none; flex-direction: column; - background-image: none; - padding-left: 0; padding: 40px 60px; } @@ -444,6 +445,7 @@ p { .people { height: auto; } + .people-number { font-size: 300px; overflow: visible; @@ -503,7 +505,6 @@ p { /* Mobile View */ @media (max-width: 600px) { - header.alt-bg { background-size: cover; padding-bottom: 1650px; @@ -547,6 +548,7 @@ p { .intro button { margin-bottom: 20px; } + .intro-image-container { display: flex; justify-content: center; @@ -556,7 +558,7 @@ p { display: block; margin: 0; width: auto; - color: #F7F779; + color: #f7f779; font-size: 40vw; line-height: 100%; font-weight: bold; @@ -626,6 +628,7 @@ p { bottom: 0; height: auto; } + .people-number { font-size: 300px; letter-spacing: 27px; @@ -635,19 +638,23 @@ p { position: relative; left: 25px; } + .people .character { width: 80px; } + #character-markup { top: -55px; - right: 60px + right: 60px; } + #character-star { bottom: -20px; left: 130px; } + #character-hat { - right: 0px; + right: 0; bottom: -15px; } diff --git a/src/static/css/normalize.css b/src/static/css/normalize.css index c46998948fb..192eb9ce433 100644 --- a/src/static/css/normalize.css +++ b/src/static/css/normalize.css @@ -8,7 +8,7 @@ * 2. Prevent adjustments of font size after orientation changes in iOS. */ - html { +html { line-height: 1.15; /* 1 */ -webkit-text-size-adjust: 100%; /* 2 */ } diff --git a/src/static/css/page.css b/src/static/css/page.css index e6c9954e637..16cd55b5385 100644 --- a/src/static/css/page.css +++ b/src/static/css/page.css @@ -6,11 +6,13 @@ grid-template-columns: 300px auto; grid-template-columns: 300px calc(100% - 300px); /* auto sometimes not set correctly on font zoom */ } + .table-wrap-container, .floating-card { border-radius: 16px; box-shadow: 0 0 16px 0 rgba(78, 85, 100, 0.2); } + .table-wrap { display: flex; margin: 0 auto; @@ -18,34 +20,18 @@ max-width: 100%; justify-content: center; } + .table-wrap-container { overflow: auto; display: inline-block; margin: 0 -16px; } -.code-block, pre { - margin: 8px 0; - padding: 24px; -} -.code-block .divider { - position: relative; - border: 1px solid #1A2B490A; - width: calc(100% + 32px); - left: -24px; -} -.code-block, pre { - overflow-y: hidden; - overflow-x: auto; -} -.code-block code { - width: 100%; -} - .index { grid-area: index; -ms-grid-column: 1; } + .index .index-box { margin: 20px 0; padding: 8px 16px; @@ -61,9 +47,11 @@ max-height: 100vh; overflow: auto; } + .index .header { - color: #1A2B49; + color: #1a2b49; } + .index-box .index-btn { padding: 14px; width: 100%; @@ -74,52 +62,64 @@ text-align: left; font-weight: bold; } + .index .header-mobile { display: none; } + .index ul { width: 100%; - margin: 0px; - padding-left: 0px; + margin: 0; + padding-left: 0; border-top: 1px solid rgba(26, 43, 73, 0.1); } + .index ul ul:first-child { border-top: none; } + .index li { position: relative; font-weight: 900; list-style-type: none; border-bottom: 1px solid rgba(26, 43, 73, 0.1); } + .index ul:last-child li:last-child { border-bottom: none; } + .index li a { display: block; padding: 24px 16px; line-height: 24px; line-height: 1.5rem; - color: #1A2B49; + color: #1a2b49; } + .index li li { font-weight: 700; border-bottom: 1px solid rgba(26, 43, 73, 0.1); } + .index li li a { padding-left: 32px; } + .index li li:last-child { border-bottom: none; } + .index li li li { font-weight: normal; border-bottom: 1px solid rgba(26, 43, 73, 0.1); } + .index li li li a { padding-left: 48px; } -.index li:before{ + +.index li::before { content: ""; width: 8px; display: inline-block; @@ -127,8 +127,9 @@ top: 24px; bottom: 24px; } -.index li.active:before{ - background-color: #A8CABA; + +.index li.active::before { + background-color: #1a2b49; } .content { @@ -137,12 +138,15 @@ margin-left: 40px; min-width: 320px; } + .content > section, .content > article { margin-bottom: 32px; } + .content ul li { list-style: none; } + .content ul li::before { position: absolute; content: "\2022"; @@ -150,20 +154,21 @@ font-size: 1rem; display: inline-block; width: 1em; - margin-left: -1em + margin-left: -1em; } .content-banner { max-width: 100%; height: auto; border-radius: 8px; - border: 1px solid #E5E5E5; + border: 1px solid #e5e5e5; } .byline { font-weight: bold; font-style: italic; } + .byline.reviewers, .byline.translators { font-weight: normal; } @@ -181,30 +186,33 @@ #num_comments { line-height: 24px; } + [data-translation] { display: none; } -.authors h2{ +.authors h2 { padding: 16px 0; } -.authors,.authors h2{ - border-bottom: 1px solid #1A2B490A; + +.authors,.authors h2 { + border-bottom: 1px solid #1a2b490a; font-size: 17px; font-size: 1.0625rem; } -.content .authors ul{ - margin:16px 0; - padding:0; + +.content .authors ul { + margin: 16px 0; + padding: 0; } -.content .authors li::before{ +.content .authors li::before { content: none; width: 0; margin-left: 0; } -.content .authors li{ +.content .authors li { list-style: none; margin: 0; padding: 0; @@ -215,7 +223,8 @@ grid-template-columns: 76px auto; grid-template-columns: 76px calc(100% - 76px); /* auto sometimes not set correctly on font zoom */ } -.authors .name{ + +.authors .name { font-size: 24px; font-size: 1.5rem; margin-right: 10px; @@ -223,78 +232,80 @@ display: inline-block; } -.authors .tagline{ +.authors .tagline { font-size: 16px; font-size: 1rem; } -.authors .avatar{ +.authors .avatar { width: 60px; height: 60px; border-radius: 50%; } + .authors .social { display: inline-block; vertical-align: middle; } + .authors .social a { display: inline-block; vertical-align: middle; margin: 0 5px; } -#chapter-navigation{ - padding:50px 36px; - border:1px solid #1A2B490A; +#chapter-navigation { + padding: 50px 36px; + border: 1px solid #1a2b490a; margin: 20px 0; overflow: hidden; } -#chapter-navigation>a{ - color:#1A2B49; - width:50%; +#chapter-navigation > a { + color: #1a2b49; + width: 50%; min-width: 100px; - display:inline-block; - position:relative; + display: inline-block; + position: relative; } -#chapter-navigation span{ - display:block; +#chapter-navigation span { + display: block; } -#chapter-navigation .chapter-no{ - font-size:22px; - font-size:1.375rem; - font-weight:bold; - font-style: italic +#chapter-navigation .chapter-no { + font-size: 22px; + font-size: 1.375rem; + font-weight: bold; + font-style: italic; } -#chapter-navigation .chapter-title{ - font-size:18px; - font-size:1.125rem; +#chapter-navigation .chapter-title { + font-size: 18px; + font-size: 1.125rem; } -#chapter-navigation .arrow{ - position:absolute; - font-size:24px; - font-size:1.5rem; - top:12px; - top:0.5em; +#chapter-navigation .arrow { + position: absolute; + font-size: 24px; + font-size: 1.5rem; + top: 12px; + top: 0.5em; } -#previous-chapter .arrow{ +#previous-chapter .arrow { transform: rotate(-90deg); - left:-24px; + left: -24px; } -#next-chapter{ - text-align:right; - float:right; +#next-chapter { + text-align: right; + float: right; } -#next-chapter .arrow{ +#next-chapter .arrow { transform: rotate(90deg); - right:-24px; + right: -24px; } aside, .note { @@ -305,6 +316,7 @@ table, figure { max-width: 100%; } + img { max-width: 100%; height: auto; @@ -327,8 +339,8 @@ figure .anchor-link { left: -25px; position: relative; float: left; - width: 0px; - height: 0px; + width: 0; + height: 0; } .fig-description-button { @@ -336,7 +348,7 @@ figure .anchor-link { font-size: 12px; font-size: 0.75rem; background-color: white; - border: 1px solid #E5E5E5; + border: 1px solid #e5e5e5; border-radius: 4px; padding: 5px; } @@ -346,7 +358,7 @@ figure .anchor-link { border-radius: 10px; margin-top: 10px; padding: 10px; - background-color: #E5E5E5; + background-color: #e5e5e5; } figure { @@ -357,54 +369,68 @@ figure { font-style: italic; overflow-x: auto; } + figure > p { display: inline-block; } + figure > a { margin: 0 auto; } + figure img { margin: 0 auto; border-radius: 8px; - border: 1px solid #E5E5E5; + border: 1px solid #e5e5e5; } + figure iframe { display: block; margin: 0 auto; } + figure .code-block { margin: 10px auto; } + figcaption { margin: 8px auto 0; text-align: center; } + table { margin: 0 auto; max-width: 100%; border-collapse: collapse; } + thead { font-family: 'Poppins', sans-serif; border-bottom: 1px solid #eee; } + th, td { padding: 10px; } + th.numeric, td.numeric { text-align: right; } + tbody tr:nth-child(even) { background-color: #f2f2f280; } + figure .big-number { text-align: center; font: bold 8rem/1em Poppins, sans-serif; color: #62718b; } + figure .fig-mobile { display: none; } + figure .fig-desktop { display: block; } @@ -430,11 +456,13 @@ figure .fig-desktop { grid-template-columns: auto; grid-template-columns: 100%; /* auto sometimes not set correctly on font zoom */ } + .main .content { -ms-grid-row: 2; -ms-grid-column: 1; margin-left: 0; } + .index { -ms-grid-row: 1; margin: 30px 0; @@ -445,18 +473,22 @@ figure .fig-desktop { justify-content: space-between; margin: 0; } + .index-box .index-btn { display: block; } + .index-box .no-button { display: none; } + .index-box .index-btn::after { font-weight: normal; float: right; content: "+"; content: "+" / ""; } + .index-box.show .index-btn::after { content: "-"; content: "-" / ""; @@ -465,25 +497,29 @@ figure .fig-desktop { .index-box ul { max-height: 0; display: none; - border-top: 0px solid #FFFFFFFF; + border-top: 0 solid #fff; transition: max-height 0.15s ease-out; overflow: hidden; } + .index-box.show ul { margin-top: 2px; - border-top: 1px solid #1A2B490A; + border-top: 1px solid #1a2b490a; max-height: 100%; display: block; transition: max-height 0.25s ease-in; } - .index li.active:before{ + + .index li.active::before { background-color: transparent; } + .table-wrap { justify-content: left; } + table { - font-size: .8em; + font-size: 0.8em; } } @@ -491,9 +527,11 @@ figure .fig-desktop { figure .big-number { font-size: 5rem; } + figure iframe { display: none; } + figure .fig-mobile { display: block; max-width: 100%; @@ -510,13 +548,16 @@ figure .fig-desktop { .index .sticky { position: static; } + .index .index-box { max-height: 100%; } + .anchor-link { padding-left: 0; margin-left: 0; } + .anchor-link:hover::before, .anchor-link:focus::before { content: ''; @@ -528,31 +569,41 @@ figure .fig-desktop { margin: 8px 0; padding: 16px; } + .code-block .divider { position: relative; - border: 1px solid #1A2B490A; + border: 1px solid #1a2b490a; width: calc(100% + 32px); left: -16px; } + .code-block pre { overflow-y: hidden; overflow-x: auto; + margin: 8px 0; + padding: 24px; } + .code-block code { width: 100%; } + .code-comment { color: #006400; } + .code-keyword { - color: #4A3244; + color: #4a3244; } + .code-function { - color: #1A2B49; + color: #1a2b49; } + .code-string { - color: #2C4A73; + color: #2c4a73; } + .code-number { - color: #0000ff; + color: #00f; } diff --git a/src/static/css/print.css b/src/static/css/print.css index 365017192e9..a0493326276 100644 --- a/src/static/css/print.css +++ b/src/static/css/print.css @@ -1,39 +1,40 @@ .top-header, .index, .discuss, #chapter-navigation, footer .navigation-logo, footer .nav-items, footer .language-switcher, footer .social-media, footer hr { - display: none; + display: none; } .alt-bg { - background-color: white; + background-color: white; } -a.btn { - display: none; +a.btn { + display: none; } h1, h2, h3, p, p.copyright, p.copyright a { - color:black; + color: black; } p.copyright { - margin: 0 auto; + margin: 0 auto; } figure iframe { - display: none; + display: none; } + figure .fig-mobile { - display: block; - max-width: 100%; + display: block; + max-width: 100%; } figure iframe.video-embed { - display: none; + display: none; } figure .video-fallback-image { - display: block; + display: block; } .fig-description-button { - display: none; + display: none; } diff --git a/src/static/css/splash.css b/src/static/css/splash.css index 1722cfcef49..283db74b89d 100644 --- a/src/static/css/splash.css +++ b/src/static/css/splash.css @@ -39,15 +39,15 @@ a:hover { @media (min-width: 800px) { img { - margin-left: -20px; + margin-left: -20px; } section { - margin-top: 20vh; + margin-top: 20vh; } section > div { - max-width: 800px; + max-width: 800px; } }