diff --git a/.all-contributorsrc b/.all-contributorsrc new file mode 100644 index 0000000000..e06f7d8b67 --- /dev/null +++ b/.all-contributorsrc @@ -0,0 +1,265 @@ +{ + "projectName": "svelte.dev", + "projectOwner": "svelte-jp", + "repoType": "github", + "repoHost": "https://github.com/", + "files": ["README.md"], + "imageSize": 100, + "commit": false, + "commitConvention": "angular", + "contributors": [ + { + "login": "tomoam", + "name": "tomoam", + "avatar_url": "https://avatars.githubusercontent.com/u/29677552?v=4", + "profile": "https://github.com/tomoam", + "contributions": ["doc"] + }, + { + "login": "myLifeAsaDog", + "name": "myLifeAsaDog", + "avatar_url": "https://avatars.githubusercontent.com/u/18300178?v=4", + "profile": "https://github.com/myLifeAsaDog", + "contributions": ["doc"] + }, + { + "login": "Makohan", + "name": "mkin", + "avatar_url": "https://avatars.githubusercontent.com/u/32333141?v=4", + "profile": "https://github.com/Makohan", + "contributions": ["doc"] + }, + { + "login": "jay-es", + "name": "Jun Shindo", + "avatar_url": "https://avatars.githubusercontent.com/u/46585162?v=4", + "profile": "https://qiita.com/jay-es", + "contributions": ["doc"] + }, + { + "login": "kkeeth", + "name": "Keeth Kuwahara", + "avatar_url": "https://avatars.githubusercontent.com/u/4125257?v=4", + "profile": "https://speakerdeck.com/clown0082", + "contributions": ["doc"] + }, + { + "login": "oekazuma", + "name": "Kazuma Oe", + "avatar_url": "https://avatars.githubusercontent.com/u/29580221?v=4", + "profile": "https://github.com/oekazuma", + "contributions": ["doc"] + }, + { + "login": "Shunpoco", + "name": "Shunpoco", + "avatar_url": "https://avatars.githubusercontent.com/u/25903627?v=4", + "profile": "https://github.com/Shunpoco", + "contributions": ["doc"] + }, + { + "login": "ampcpmgp", + "name": "ampcpmgp", + "avatar_url": "https://avatars.githubusercontent.com/u/13173632?v=4", + "profile": "https://github.com/ampcpmgp", + "contributions": ["doc"] + }, + { + "login": "takoyaro", + "name": "Jimmy", + "avatar_url": "https://avatars.githubusercontent.com/u/54836677?v=4", + "profile": "https://github.com/takoyaro", + "contributions": ["doc"] + }, + { + "login": "jdkfx", + "name": "Haruki Tazoe", + "avatar_url": "https://avatars.githubusercontent.com/u/40142697?v=4", + "profile": "https://github.com/jdkfx", + "contributions": ["doc"] + }, + { + "login": "shin1127", + "name": "shin1127", + "avatar_url": "https://avatars.githubusercontent.com/u/56531152?v=4", + "profile": "https://shin1127.github.io/myPortfolio/", + "contributions": ["doc"] + }, + { + "login": "manak1", + "name": "manaki", + "avatar_url": "https://avatars.githubusercontent.com/u/32151765?v=4", + "profile": "https://twilink.click/mikeanakida", + "contributions": ["doc"] + }, + { + "login": "knj4484", + "name": "knj4484", + "avatar_url": "https://avatars.githubusercontent.com/u/11140280?v=4", + "profile": "https://github.com/knj4484", + "contributions": ["doc"] + }, + { + "login": "miily8310s", + "name": "miruoo", + "avatar_url": "https://avatars.githubusercontent.com/u/42486288?v=4", + "profile": "https://katanugramer.hatenablog.com/", + "contributions": ["doc"] + }, + { + "login": "mouse484", + "name": "mouse_484", + "avatar_url": "https://avatars.githubusercontent.com/u/38714187?v=4", + "profile": "https://portfolio.mouse484.tk/", + "contributions": ["doc"] + }, + { + "login": "dynamis", + "name": "dynamis", + "avatar_url": "https://avatars.githubusercontent.com/u/188166?v=4", + "profile": "http://dynamis.jp/", + "contributions": ["financial", "infra"] + }, + { + "login": "Murayu0225", + "name": "Yu Muramatsu", + "avatar_url": "https://avatars.githubusercontent.com/u/37988559?v=4", + "profile": "https://github.com/Murayu0225", + "contributions": ["doc"] + }, + { + "login": "lunain84", + "name": "HirosuguTakeshita", + "avatar_url": "https://avatars.githubusercontent.com/u/52437973?v=4", + "profile": "https://qiita.com/fuwasegu", + "contributions": ["doc"] + }, + { + "login": "yamanoku", + "name": "Okuto Oyama", + "avatar_url": "https://avatars.githubusercontent.com/u/1996642?v=4", + "profile": "https://yamanoku.net/", + "contributions": ["doc"] + }, + { + "login": "baseballyama", + "name": "Yuichiro Yamashita", + "avatar_url": "https://avatars.githubusercontent.com/u/19153718?v=4", + "profile": "https://github.com/baseballyama", + "contributions": ["doc"] + }, + { + "login": "nullnyat", + "name": "Nullcat chan!", + "avatar_url": "https://avatars.githubusercontent.com/u/89781396?v=4", + "profile": "https://keybase.io/nullnyat", + "contributions": ["doc"] + }, + { + "login": "komura-c", + "name": "Yuki Ishii", + "avatar_url": "https://avatars.githubusercontent.com/u/37304826?v=4", + "profile": "https://github.com/komura-c", + "contributions": ["doc"] + }, + { + "login": "torish14", + "name": "torish14", + "avatar_url": "https://avatars.githubusercontent.com/u/49876561?v=4", + "profile": "https://sukimakakumei.co.jp/", + "contributions": ["doc"] + }, + { + "login": "kokko-san", + "name": "kokko-san", + "avatar_url": "https://avatars.githubusercontent.com/u/36446753?v=4", + "profile": "https://github.com/kokko-san", + "contributions": ["doc"] + }, + { + "login": "ota-meshi", + "name": "Yosuke Ota", + "avatar_url": "https://avatars.githubusercontent.com/u/16508807?v=4", + "profile": "https://ota-meshi.github.io/", + "contributions": ["doc"] + }, + { + "login": "dajiaji", + "name": "Ajitomi Daisuke", + "avatar_url": "https://avatars.githubusercontent.com/u/3192030?v=4", + "profile": "https://github.com/dajiaji", + "contributions": ["doc"] + }, + { + "login": "mitsu-ksgr", + "name": "mitsu-ksgr", + "avatar_url": "https://avatars.githubusercontent.com/u/3091232?v=4", + "profile": "http://mitsu-ksgr.github.io/", + "contributions": ["doc"] + }, + { + "login": "tatsuyafw", + "name": "Tatsuya Hoshino", + "avatar_url": "https://avatars.githubusercontent.com/u/1162665?v=4", + "profile": "http://tatsuyafw.hatenablog.jp/", + "contributions": ["doc"] + }, + { + "login": "kimdj2", + "name": "bondee", + "avatar_url": "https://avatars.githubusercontent.com/u/38813699?v=4", + "profile": "https://github.com/kimdj2", + "contributions": ["doc"] + }, + { + "login": "dito", + "name": "dito", + "avatar_url": "https://avatars.githubusercontent.com/u/4264269?v=4", + "profile": "https://github.com/dito", + "contributions": ["doc"] + }, + { + "login": "shuuji3", + "name": "TAKAHASHI Shuuji", + "avatar_url": "https://avatars.githubusercontent.com/u/1425259?v=4", + "profile": "https://shuuji3.xyz/", + "contributions": ["doc"] + }, + { + "login": "yo-goto", + "name": "PADAone", + "avatar_url": "https://avatars.githubusercontent.com/u/50942816?v=4", + "profile": "https://github.com/yo-goto", + "contributions": ["doc"] + }, + { + "login": "yuki0418", + "name": "Yuki Ishii", + "avatar_url": "https://avatars.githubusercontent.com/u/45615348?v=4", + "profile": "https://github.com/yuki0418", + "contributions": ["doc"] + }, + { + "login": "tada-tsu", + "name": "Tadatsugu Ohno", + "avatar_url": "https://avatars.githubusercontent.com/u/34794025?v=4", + "profile": "https://github.com/tada-tsu", + "contributions": ["doc"] + }, + { + "login": "akku1139", + "name": "-akku-", + "avatar_url": "https://avatars.githubusercontent.com/u/151517253?v=4", + "profile": "https://github.com/akku1139", + "contributions": ["doc"] + }, + { + "login": "jill64", + "name": "jill64", + "avatar_url": "https://avatars.githubusercontent.com/u/143883742?v=4", + "profile": "https://github.com/jill64", + "contributions": ["doc"] + } + ], + "contributorsPerLine": 7 +} diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index d632634540..0000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -open_collective: svelte diff --git a/.github/ISSUE_TEMPLATE/improve_translation.md b/.github/ISSUE_TEMPLATE/improve_translation.md new file mode 100644 index 0000000000..c4b2c17994 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/improve_translation.md @@ -0,0 +1,40 @@ +--- +name: 誤字・脱字・誤訳報告、翻訳改善要望(report typos and mistranslations, or request improvements in translation) +about: 誤字・脱字・誤訳の報告や翻訳改善の要望 +title: "{対象ドキュメント}の翻訳改善要望" +labels: documentation, translation +assignees: '' +--- + +## 対象ドキュメント + + + +## 対象箇所 + + + + +## 修正したい/してほしい + + +- 修正したい +- 修正してほしい + + +## 備考 + + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/other.md b/.github/ISSUE_TEMPLATE/other.md new file mode 100644 index 0000000000..f01e8f9f12 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other.md @@ -0,0 +1,9 @@ +--- +name: その他 +about: Describe this issue template's purpose here. +title: '' +labels: '' +assignees: '' + +--- + diff --git a/.github/ISSUE_TEMPLATE/request_translation.md b/.github/ISSUE_TEMPLATE/request_translation.md new file mode 100644 index 0000000000..e3bd3357a4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/request_translation.md @@ -0,0 +1,29 @@ +--- +name: 翻訳ドキュメント追加(add the document to be translated) +about: 翻訳したい/してほしいドキュメント +title: "{対象ドキュメント}の翻訳" +labels: documentation, translation +assignees: '' + +--- + +## 対象ドキュメント + + + + +## 翻訳したい/してほしい + + +- 翻訳したい +- 翻訳してほしい + + +## 備考 + + \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 1b601151d9..0000000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,9 +0,0 @@ -### A note on documentation PRs - -If this is a documentation PR (i.e. changing content within `apps/svelte.dev/content/docs`), then this is the wrong repository to make those changes. The content in this folder is synced from other repositories. Therefore, these changes should be made in their respective repositories (at https://github.com/sveltejs/svelte or https://github.com/sveltejs/kit, or example). - -### Before submitting the PR, please make sure you do the following - -- [ ] It's really useful if your PR references an issue where it is discussed ahead of time. -- [ ] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`. -- [ ] This message body should clearly illustrate what problems it solves. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index bf47827d68..0000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: CI -on: - push: - branches: [main] - pull_request: -permissions: - contents: read # to fetch code (actions/checkout) - -env: - # We only install Chromium manually - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' - -jobs: - # unskip once we have tutorial here which runs playwright tests - # Tests: - # runs-on: ${{ matrix.os }} - # timeout-minutes: 15 - # strategy: - # matrix: - # include: - # - node-version: 18 - # os: windows-latest - # - node-version: 18 - # os: macOS-latest - # - node-version: 18 - # os: ubuntu-latest - # - node-version: 20 - # os: ubuntu-latest - # - node-version: 22 - # os: ubuntu-latest - - # steps: - # - uses: actions/checkout@v3 - # - uses: pnpm/action-setup@v4 - # - uses: actions/setup-node@v3 - # with: - # node-version: ${{ matrix.node-version }} - # cache: pnpm - # - run: pnpm install --frozen-lockfile - # - run: pnpm playwright install chromium - # - run: pnpm test - # env: - # CI: true - Lint: - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - uses: actions/checkout@v3 - - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v3 - with: - node-version: 18 - cache: pnpm - - name: install - run: pnpm install --frozen-lockfile - - name: type check - run: pnpm -r package && pnpm check - - name: lint - if: (${{ success() }} || ${{ failure() }}) # ensures this step runs even if previous steps fail (avoids multiple runs uncovering different issues at different steps) - run: pnpm lint diff --git a/.github/workflows/docs-preview-create.yml b/.github/workflows/docs-preview-create.yml deleted file mode 100644 index 5c9f983245..0000000000 --- a/.github/workflows/docs-preview-create.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Docs preview create - -on: - workflow_dispatch: - inputs: - repo: - description: 'Repository name (not fully-qualified, eg. `svelte` or `kit`)' - required: true - type: string - pr: - description: 'PR number' - required: true - type: string - owner: - description: 'Owner (eg. sveltejs)' - required: true - type: string - branch: - description: 'Branch (eg. my-feature-branch)' - required: true - type: string - -permissions: - contents: write - -env: - BRANCH: preview-${{ inputs.repo }}-${{ inputs.pr }} - -jobs: - Sync: - name: Sync - runs-on: ubuntu-latest - - concurrency: - group: preview-${{ inputs.repo }}-${{ inputs.pr }} # can't reference env here - cancel-in-progress: true - - steps: - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: pnpm - - run: pnpm install --frozen-lockfile - - - name: Checkout - run: git fetch origin ${{ env.BRANCH }} && git checkout ${{ env.BRANCH }} || git checkout -b ${{ env.BRANCH }} - - - name: Sync - run: cd apps/svelte.dev && pnpm sync-docs --owner="${{ inputs.owner }}" -p "${{ inputs.repo }}#${{ inputs.branch }}" - - - name: Configure Git - run: | - git config --global user.name "GitHub Actions Bot" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - - - name: Push - id: push - run: git add -A && git commit -m "sync docs" && git push -u origin ${{ env.BRANCH }} - - - name: Request preview comment - uses: peter-evans/repository-dispatch@v3 - with: - event-type: 'request-preview-comment' - client-payload: |- - { - "repo": "${{ inputs.repo }}", - "pr": "${{ inputs.pr }}" - } diff --git a/.github/workflows/docs-preview-delete.yml b/.github/workflows/docs-preview-delete.yml deleted file mode 100644 index faa13fbade..0000000000 --- a/.github/workflows/docs-preview-delete.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Docs preview delete - -on: - workflow_dispatch: - inputs: - repo: - description: 'Repository name (not fully-qualified, eg. `svelte` or `kit`)' - required: true - type: string - pr: - description: 'PR number' - required: true - type: string - -env: - BRANCH: preview-${{ inputs.repo }}-${{ inputs.pr }} - -jobs: - Sync: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - - name: Delete branch - run: git push origin :${{ env.BRANCH }} diff --git a/.github/workflows/sync-docs.yml b/.github/workflows/sync-docs.yml deleted file mode 100644 index 79b5a9727f..0000000000 --- a/.github/workflows/sync-docs.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Sync docs - -on: - workflow_dispatch: - inputs: - repo: - description: 'Repository name (not fully-qualified, eg. `svelte` or `kit`)' - required: true - type: string - -permissions: - contents: write - pull-requests: write - -jobs: - Sync: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: pnpm - - run: pnpm install --frozen-lockfile - - - name: Sync - run: cd apps/svelte.dev && pnpm sync-docs -p ${{ inputs.repo }} - - - name: Create or update pull request - uses: peter-evans/create-pull-request@v7 - with: - commit-message: sync ${{ inputs.repo }} docs - title: Sync `${{ inputs.repo }}` docs - body: This is an automated pull request. See the [README](../tree/main/apps/svelte.dev/scripts/sync-docs/README.md) for more information - branch: sync-${{ inputs.repo }} - base: main diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..7a94bfbac8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,202 @@ +# svelte-jp/svelte.dev への貢献について + +svelte-jp/svelte.dev はSvelte公式ドキュメントサイトの日本語化プロジェクトです。 + +このリポジトリは[sveltejs/svelte.dev](https://github.com/sveltejs/svelte.dev)をフォークして作成されており、ライセンスやコミュニティ・コラボレーションの精神についてはSvelte本体のそれを引き継ぎます。 + +Svelte公式のCONTRIBUTING.mdはこちらです、是非ご一読ください。 + +- [CONTRIBUTING.md - sveltejs/svelte](https://github.com/sveltejs/svelte/blob/main/CONTRIBUTING.md) + + +## 貢献するには + +貢献する方法はたくさんあり、その多くはコードを書く必要もなければ、いきなり翻訳する必要もありません。 + +- 日本語ドキュメントサイト([https://svelte.jp/](https://svelte.jp/))を使ってみてください。気になるところや改善点があれば[Issueを開いて](#issueを作成する)お知らせください。 +- 翻訳で貢献されたい場合は[翻訳作業について](#翻訳作業について)をチェックしてみてください。翻訳にはみなさんの協力が必要です。誤訳があっても誤字・脱字があっても単語が統一できていなくても構いません、後からみんなで良くしていければと考えています。 + +貢献は大歓迎です!もし貢献を迷っていたり、貢献に助けが必要であれば[Svelte日本のDiscord](https://discord.com/invite/YTXq3ZtBbx)で知らせてください。 + + +## ディレクトリ構成・翻訳の仕組み + +ドキュメントのファイルはこのリポジトリの [`apps/svelte.dev/content`](https://github.com/svelte-jp/svelte.dev/tree/main/apps/svelte.dev/content) ディレクトリにあります。 + +- **blog** + - Blogは apps/svelte.dev/content/blog 配下にあります。 +- **docs** + - Docsは apps/svelte.dev/content/docs 配下にあります。CLI、SvelteKit、Svelte本体のドキュメントがそれぞれディレクトリで分かれています。 + - cli: CLI ツールのドキュメントがあります。 + - kit: SvelteKit のドキュメントがあります。 + - svelte: Svelte のドキュメントがあります +- **tutorial** + - tutorial は apps/svelte.dev/content/tutorial 配下のそれぞれの章ごとに `index.md` というファイルがあります。 + +``` +apps/svelte.dev/content +├── blog +│   ├── 2016-11-26-frameworks-without-the-framework.md # <- blog +│   ... +│ +├── docs +│   ├── cli +│   │   ├── 10-introduction +│   │   │ ├── 10-overview.md # <- CLI のドキュメント +│   │   │ ... +│   │   ... +│   │   +│   ├── kit +│   │   ├── 10-getting-started +│   │   │ ├── 10-introduction.md # <- SvelteKit のドキュメント +│   │   │ ... +│   │   ... +│   │ +│   ├── svelte +│   │   ├── 01-introduction +│   │   │ ├── 01-introduction.md # <- Svelte のドキュメント +│   │   │ ... +│   │   ... +│   ... +│ +├── examples +│ +└── tutorial + ├── 01-svelte + │ ├── 01-introduction + │ │ ├── 01-welcome-to-svelte + │ │ │ ├── +assets... + │ │ │ └── index.md # <- tutorial + │ │ ... + │ ... + ... +``` + +サイトのソース、TOPページの日本語訳は [apps/svelte.dev/src](https://github.com/svelte-jp/svelte.dev/tree/main/apps/svelte.dev/src) にあります。 + + +## 翻訳の流れ + +### 1. 翻訳するドキュメントを選ぶ + +翻訳が必要な文書は[issue](https://github.com/svelte-jp/svelte.dev/issues?q=is%3Aopen+is%3Aissue)が作成されています。 + +まだ誰も着手していないIssueには`翻訳者募集中`というLabelがついています。翻訳したいものがあれば、Issueのコメントで知らせてください(堅苦しい挨拶などは不要です。「この翻訳やりましょうか?」と言っていただけたらそれだけでとても嬉しいです!)。 + +運営側から依頼する旨をコメントで返信しますので、その後に作業を開始してください。 + +もし翻訳したいドキュメントのIssueがなければ、Issueを作成してください。 + + +### 2. 翻訳作業 + +このリポジトリをForkし、ローカルにcloneしてください。 + +``` +git clone https://github.com/{USER}/svelte.dev.git +``` + +[ディレクトリ構成・翻訳の仕組み](#ディレクトリ構成翻訳の仕組み)を参考に、担当する文書を見つけてください。 + +実際の翻訳については[翻訳のガイドライン](#翻訳のガイドライン)を参考にしてください。 + +> いきなり完璧な翻訳を目指さなくても大丈夫です。PRに間違いや誤字・脱字があっても大丈夫です。ちゃんとレビューをしますし、レビューで怒ったりしませんのでご安心ください。それより、あなたがこのプロジェクトに貢献するため時間と労力を割いてくれたことに感謝しかありません。 + + +#### 2-1. 見出しの翻訳について + +マークダウンでは、行の先頭に `#` が付けられた行は見出し要素になります。 +この見出し要素には自動で id が割り付けられ、ページ内の特定の位置にフォーカスさせることができるようになっています。 + +例えば、以下のようなマークダウンの場合... + +```markdown +## Alternatives to SvelteKit +``` + +...以下のような HTML に変換されます。 + +```html +

+ Alternatives to SvelteKit + +

+``` + +この自動で id を割り振る仕組みは、マルチバイト文字に対応していません。 +また、もし対応していたとしても、本来割り振られる id とは異なるものになってしまいます。 +それを防ぐため、見出しの翻訳をする場合は、HTML のコメント要素を使用して id を指定します。 + +```markdown +## SvelteKit の代替手段 +``` + +こうすると、以下のような HTML に変換されるようになります。 + +```html +

+ SvelteKit の代替手段 + +

+``` + +実際のソースはこちら: +https://github.com/svelte-jp/svelte.dev/blob/0f7d41d94f1a67036b736ddcabb00f9c24850ba2/apps/svelte.dev/content/docs/svelte/01-introduction/02-getting-started.md?plain=1#L17 + +### 3. lintの実行 + +※現在 lint は調整中ですので、無視して先に進めてください。 + + +### 4. Pull Request作成 + +Fork元にPull Requestを提出してください。Pull RequestのコメントにはIssueの番号を含めてください。レビュー後、問題がなければマージされます。 +PRに間違いや誤字・脱字、ガイドライン違反があっても大丈夫です。間違いを恐れないでください。 + + +### 文体 + +「だである」ではなく「ですます」調を使用してください。 + + +### 改行位置を原文と揃える + +可能な限り、原文と翻訳文の行数を揃え、更新時のdiffチェックが楽になるように協力してください。 + + +### 単語、表記ゆれ + +※単語、表記揺れについては現在準備中ですので、無視して先に進めてください。 + + +### ダッシュ + +原文で使われているダッシュは、以下のように場合に応じて訳し分けてください。 + +- 和訳で文中に埋め込まれるような語句を区切っている場合、ダッシュの代わりに括弧でその語句を囲んでください +- 和訳で文と文の区切りになっている場合、ダッシュの代わりに句点(`。`)を打ってください +- 箇条書きの項目と説明を区切っている場合、ダッシュをそのままにする + + +## issueを作成する + +何かお気づきの点などがある場合はお気軽にissueを作成して頂いて構いません。 +以下のテンプレートを用意しております。 + +- 翻訳ドキュメント追加 + - 翻訳したい/してほしいドキュメントがissueになければこちらをご使用ください。 +- 誤字・脱字・誤訳報告、翻訳改善要望 + - 誤字・脱字・誤訳や、不自然な言い回しやよりより翻訳文があればこちらをご使用ください。 +- その他 + - ご質問、ご意見、お気軽にどうぞ! + + +## その他 + +- Svelte本体の変更は大体月に1度のペースで日本語サイトにも反映を行います。これは、Svelte本体のサイトが大体月に1度(月初、毎月のNewsletterが入るタイミング)で更新されるためです。 + Svelte本体のサイトに緊急で更新がある場合はなるべくそれに追従したいと考えています。 + + +## 備考 + +翻訳の進め方やCONTRIBUTING.mdに記載する内容などは、各フロントエンドフレームワーク及びライブラリの日本語化プロジェクトである、[angular/angular-ja](https://github.com/angular/angular-ja)、[vuejs/jp.vuejs.org](https://github.com/vuejs/jp.vuejs.org), [reactjs/ja.reactjs.org](https://github.com/reactjs/ja.reactjs.org)を参考にさせて頂きました。 diff --git a/README.md b/README.md index 05e91ecddf..d9aaea23b3 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,97 @@ +# Svelte site Japanese translation + +[Svelte](https://github.com/sveltejs/svelte)の公式ドキュメントサイト [svelte.dev](https://svelte.dev/) を日本語に翻訳するプロジェクトです。 + +**日本語ドキュメントサイト URL: https://svelte.jp** + +Svelte は素晴らしいツールで、公式ドキュメント及びチュートリアルも非常に素晴らしいです。公式からは英語版のみ提供されていますが、日本語に翻訳されたドキュメントとチュートリアルがあれば日本語話者にとってはもっと学習しやすくなると考えています。 + +## 貢献(Contribution)について + +この翻訳プロジェクトではみなさんの貢献を歓迎しています! + +貢献の形は様々で、翻訳はもちろん、誤字・脱字・誤訳の報告、よりよい翻訳文の提案、翻訳してほしいページのリクエスト、その他翻訳だけでなく Svelte Japan Community を良くするためのご意見なども大歓迎です! + +興味がある方は [CONTRIBUTING.md](https://github.com/svelte-jp/svelte.dev/blob/main/CONTRIBUTING.md) をご参照ください。 + +ご意見や気が付いたことがあれば、お気軽に Issue を作成して知らせてください。 + +もしくは [Svelte 日本の Discord](https://discord.com/invite/YTXq3ZtBbx) の `#ドキュメント翻訳`チャンネルに投稿頂いても構いません。 + + +## Contributors ✨ + +日本語翻訳に貢献してくれたコントリビューターの皆さんはこちらです! +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
tomoam
tomoam

📗📘📖
myLifeAsaDog
myLifeAsaDog

📗📘
mkin
mkin

📗
Jun Shindo
Jun Shindo

📗
Keeth Kuwahara
Keeth Kuwahara

📗
Kazuma Oe
Kazuma Oe

📗📘📖
Shunpoco
Shunpoco

📗
ampcpmgp
ampcpmgp

📗
Jimmy
Jimmy

📗
Haruki Tazoe
Haruki Tazoe

📗
shin1127
shin1127

📗
manaki
manaki

📗
knj4484
knj4484

📗
miruoo
miruoo

📗📘
mouse_484
mouse_484

📗
dynamis
dynamis

💵 🚇
Yu Muramatsu
Yu Muramatsu

📗
HirosuguTakeshita
HirosuguTakeshita

📗
Okuto Oyama
Okuto Oyama

📗📘
Yuichiro Yamashita
Yuichiro Yamashita

📗
Nullcat chan!
Nullcat chan!

📗
Yuki Ishii
Yuki Ishii

📗
torish14
torish14

📗
kokko-san
kokko-san

📗
Yosuke Ota
Yosuke Ota

📗
Ajitomi Daisuke
Ajitomi Daisuke

📘
mitsu-ksgr
mitsu-ksgr

📗
Tatsuya Hoshino
Tatsuya Hoshino

📗
bondee
bondee

📘
dito
dito

📘
TAKAHASHI Shuuji
TAKAHASHI Shuuji

📗
PADAone
PADAone

📗
Yuki Ishii
Yuki Ishii

📖
Tadatsugu Ohno
Tadatsugu Ohno

📖
-akku-
-akku-

📖
jill64
jill64

📖
+ + + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! + + +以下はSvelte公式のREADMEの内容です。 + +--- + # svelte.dev This is the repository behind [svelte.dev](https://svelte.dev), the official Svelte site, and the related packages that it relies on. diff --git a/apps/kit.svelte.dev/vercel.json b/apps/kit.svelte.dev/vercel.json index 6b9ecfbe6e..639c67a8ad 100644 --- a/apps/kit.svelte.dev/vercel.json +++ b/apps/kit.svelte.dev/vercel.json @@ -3,36 +3,36 @@ "redirects": [ { "source": "/", - "destination": "https://svelte.dev/", + "destination": "https://svelte.jp/", "permanent": true }, { "source": "/docs/layouts", - "destination": "https://svelte.dev/docs/kit/routing", + "destination": "https://svelte.jp/docs/kit/routing", "permanent": true }, { "source": "/docs/loading", - "destination": "https://svelte.dev/docs/kit/load", + "destination": "https://svelte.jp/docs/kit/load", "permanent": true }, { "source": "/docs/types", - "destination": "https://svelte.dev/docs/kit/@sveltejs-kit" + "destination": "https://svelte.jp/docs/kit/@sveltejs-kit" }, { "source": "/docs", - "destination": "https://svelte.dev/docs/kit", + "destination": "https://svelte.jp/docs/kit", "permanent": true }, { "source": "/docs/(.*)", - "destination": "https://svelte.dev/docs/kit/$1", + "destination": "https://svelte.jp/docs/kit/$1", "permanent": true }, { "source": "/(.*)", - "destination": "https://svelte.dev/" + "destination": "https://svelte.jp/" } ] } diff --git a/apps/learn.svelte.dev/vercel.json b/apps/learn.svelte.dev/vercel.json index 806baa00c2..0b7298c36c 100644 --- a/apps/learn.svelte.dev/vercel.json +++ b/apps/learn.svelte.dev/vercel.json @@ -3,95 +3,95 @@ "redirects": [ { "source": "/tutorial/welcome-to-svelte", - "destination": "https://svelte.dev/tutorial/svelte/welcome-to-svelte" + "destination": "https://svelte.jp/tutorial/svelte/welcome-to-svelte" }, { "source": "/tutorial/your-first-component", - "destination": "https://svelte.dev/tutorial/svelte/your-first-component" + "destination": "https://svelte.jp/tutorial/svelte/your-first-component" }, { "source": "/tutorial/dynamic-attributes", - "destination": "https://svelte.dev/tutorial/svelte/dynamic-attributes" + "destination": "https://svelte.jp/tutorial/svelte/dynamic-attributes" }, { "source": "/tutorial/styling", - "destination": "https://svelte.dev/tutorial/svelte/styling" + "destination": "https://svelte.jp/tutorial/svelte/styling" }, { "source": "/tutorial/nested-components", - "destination": "https://svelte.dev/tutorial/svelte/nested-components" + "destination": "https://svelte.jp/tutorial/svelte/nested-components" }, { "source": "/tutorial/html-tags", - "destination": "https://svelte.dev/tutorial/svelte/html-tags" + "destination": "https://svelte.jp/tutorial/svelte/html-tags" }, { "source": "/tutorial/reactive-assignments", - "destination": "https://svelte.dev/tutorial/svelte/state" + "destination": "https://svelte.jp/tutorial/svelte/state" }, { "source": "/tutorial/reactive-declarations", - "destination": "https://svelte.dev/tutorial/svelte/derived-state" + "destination": "https://svelte.jp/tutorial/svelte/derived-state" }, { "source": "/tutorial/reactive-statements", - "destination": "https://svelte.dev/tutorial/svelte/effects" + "destination": "https://svelte.jp/tutorial/svelte/effects" }, { "source": "/tutorial/updating-arrays-and-objects", - "destination": "https://svelte.dev/tutorial/svelte/deep-state" + "destination": "https://svelte.jp/tutorial/svelte/deep-state" }, { "source": "/tutorial/declaring-props", - "destination": "https://svelte.dev/tutorial/svelte/declaring-props" + "destination": "https://svelte.jp/tutorial/svelte/declaring-props" }, { "source": "/tutorial/default-values", - "destination": "https://svelte.dev/tutorial/svelte/default-values" + "destination": "https://svelte.jp/tutorial/svelte/default-values" }, { "source": "/tutorial/spread-props", - "destination": "https://svelte.dev/tutorial/svelte/spread-props" + "destination": "https://svelte.jp/tutorial/svelte/spread-props" }, { "source": "/tutorial/if-blocks", - "destination": "https://svelte.dev/tutorial/svelte/if-blocks" + "destination": "https://svelte.jp/tutorial/svelte/if-blocks" }, { "source": "/tutorial/else-blocks", - "destination": "https://svelte.dev/tutorial/svelte/else-blocks" + "destination": "https://svelte.jp/tutorial/svelte/else-blocks" }, { "source": "/tutorial/else-if-blocks", - "destination": "https://svelte.dev/tutorial/svelte/else-if-blocks" + "destination": "https://svelte.jp/tutorial/svelte/else-if-blocks" }, { "source": "/tutorial/each-blocks", - "destination": "https://svelte.dev/tutorial/svelte/each-blocks" + "destination": "https://svelte.jp/tutorial/svelte/each-blocks" }, { "source": "/tutorial/keyed-each-blocks", - "destination": "https://svelte.dev/tutorial/svelte/keyed-each-blocks" + "destination": "https://svelte.jp/tutorial/svelte/keyed-each-blocks" }, { "source": "/tutorial/await-blocks", - "destination": "https://svelte.dev/tutorial/svelte/await-blocks" + "destination": "https://svelte.jp/tutorial/svelte/await-blocks" }, { "source": "/tutorial/dom-events", - "destination": "https://svelte.dev/tutorial/svelte/dom-events" + "destination": "https://svelte.jp/tutorial/svelte/dom-events" }, { "source": "/tutorial/inline-handlers", - "destination": "https://svelte.dev/tutorial/svelte/inline-handlers" + "destination": "https://svelte.jp/tutorial/svelte/inline-handlers" }, { "source": "/tutorial/event-modifiers", - "destination": "https://svelte.dev/tutorial/svelte/capturing" + "destination": "https://svelte.jp/tutorial/svelte/capturing" }, { "source": "/tutorial/component-events", - "destination": "https://svelte.dev/tutorial/svelte/component-events" + "destination": "https://svelte.jp/tutorial/svelte/component-events" }, { "source": "/tutorial/event-forwarding", @@ -99,47 +99,47 @@ }, { "source": "/tutorial/dom-event-forwarding", - "destination": "https://svelte.dev/tutorial/svelte/spreading-events" + "destination": "https://svelte.jp/tutorial/svelte/spreading-events" }, { "source": "/tutorial/text-inputs", - "destination": "https://svelte.dev/tutorial/svelte/text-inputs" + "destination": "https://svelte.jp/tutorial/svelte/text-inputs" }, { "source": "/tutorial/numeric-inputs", - "destination": "https://svelte.dev/tutorial/svelte/numeric-inputs" + "destination": "https://svelte.jp/tutorial/svelte/numeric-inputs" }, { "source": "/tutorial/checkbox-inputs", - "destination": "https://svelte.dev/tutorial/svelte/checkbox-inputs" + "destination": "https://svelte.jp/tutorial/svelte/checkbox-inputs" }, { "source": "/tutorial/select-bindings", - "destination": "https://svelte.dev/tutorial/svelte/select-bindings" + "destination": "https://svelte.jp/tutorial/svelte/select-bindings" }, { "source": "/tutorial/group-inputs", - "destination": "https://svelte.dev/tutorial/svelte/group-inputs" + "destination": "https://svelte.jp/tutorial/svelte/group-inputs" }, { "source": "/tutorial/multiple-select-bindings", - "destination": "https://svelte.dev/tutorial/svelte/multiple-select-bindings" + "destination": "https://svelte.jp/tutorial/svelte/multiple-select-bindings" }, { "source": "/tutorial/textarea-inputs", - "destination": "https://svelte.dev/tutorial/svelte/textarea-inputs" + "destination": "https://svelte.jp/tutorial/svelte/textarea-inputs" }, { "source": "/tutorial/marked", - "destination": "https://svelte.dev/tutorial/svelte/textarea-inputs" + "destination": "https://svelte.jp/tutorial/svelte/textarea-inputs" }, { "source": "/tutorial/onmount", - "destination": "https://svelte.dev/docs/svelte/lifecycle-hooks" + "destination": "https://svelte.jp/docs/svelte/lifecycle-hooks" }, { "source": "/tutorial/update", - "destination": "https://svelte.dev/docs/svelte/lifecycle-hooks" + "destination": "https://svelte.jp/docs/svelte/lifecycle-hooks" }, { "source": "/tutorial/elizabot", @@ -147,27 +147,27 @@ }, { "source": "/tutorial/tick", - "destination": "https://svelte.dev/docs/svelte/lifecycle-hooks#tick" + "destination": "https://svelte.jp/docs/svelte/lifecycle-hooks#tick" }, { "source": "/tutorial/writable-stores", - "destination": "https://svelte.dev/tutorial/svelte/introducing-stores" + "destination": "https://svelte.jp/tutorial/svelte/introducing-stores" }, { "source": "/tutorial/auto-subscriptions", - "destination": "https://svelte.dev/docs/svelte/stores" + "destination": "https://svelte.jp/docs/svelte/stores" }, { "source": "/tutorial/readable-stores", - "destination": "https://svelte.dev/docs/svelte/stores" + "destination": "https://svelte.jp/docs/svelte/stores" }, { "source": "/tutorial/derived-stores", - "destination": "https://svelte.dev/docs/svelte/stores" + "destination": "https://svelte.jp/docs/svelte/stores" }, { "source": "/tutorial/custom-stores", - "destination": "https://svelte.dev/docs/svelte/stores" + "destination": "https://svelte.jp/docs/svelte/stores" }, { "source": "/tutorial/store-bindings", @@ -175,399 +175,399 @@ }, { "source": "/tutorial/tweens", - "destination": "https://svelte.dev/tutorial/svelte/tweens" + "destination": "https://svelte.jp/tutorial/svelte/tweens" }, { "source": "/tutorial/springs", - "destination": "https://svelte.dev/tutorial/svelte/springs" + "destination": "https://svelte.jp/tutorial/svelte/springs" }, { "source": "/tutorial/transition", - "destination": "https://svelte.dev/tutorial/svelte/transition" + "destination": "https://svelte.jp/tutorial/svelte/transition" }, { "source": "/tutorial/adding-parameters-to-transitions", - "destination": "https://svelte.dev/tutorial/svelte/adding-parameters-to-transitions" + "destination": "https://svelte.jp/tutorial/svelte/adding-parameters-to-transitions" }, { "source": "/tutorial/in-and-out", - "destination": "https://svelte.dev/tutorial/svelte/in-and-out" + "destination": "https://svelte.jp/tutorial/svelte/in-and-out" }, { "source": "/tutorial/custom-css-transitions", - "destination": "https://svelte.dev/tutorial/svelte/custom-css-transitions" + "destination": "https://svelte.jp/tutorial/svelte/custom-css-transitions" }, { "source": "/tutorial/custom-js-transitions", - "destination": "https://svelte.dev/tutorial/svelte/custom-js-transitions" + "destination": "https://svelte.jp/tutorial/svelte/custom-js-transitions" }, { "source": "/tutorial/transition-events", - "destination": "https://svelte.dev/tutorial/svelte/transition-events" + "destination": "https://svelte.jp/tutorial/svelte/transition-events" }, { "source": "/tutorial/global-transitions", - "destination": "https://svelte.dev/tutorial/svelte/global-transitions" + "destination": "https://svelte.jp/tutorial/svelte/global-transitions" }, { "source": "/tutorial/key-blocks", - "destination": "https://svelte.dev/tutorial/svelte/key-blocks" + "destination": "https://svelte.jp/tutorial/svelte/key-blocks" }, { "source": "/tutorial/deferred-transitions", - "destination": "https://svelte.dev/tutorial/svelte/deferred-transitions" + "destination": "https://svelte.jp/tutorial/svelte/deferred-transitions" }, { "source": "/tutorial/animate", - "destination": "https://svelte.dev/tutorial/svelte/animations" + "destination": "https://svelte.jp/tutorial/svelte/animations" }, { "source": "/tutorial/actions", - "destination": "https://svelte.dev/tutorial/svelte/actions" + "destination": "https://svelte.jp/tutorial/svelte/actions" }, { "source": "/tutorial/adding-parameters-to-actions", - "destination": "https://svelte.dev/tutorial/svelte/adding-parameters-to-actions" + "destination": "https://svelte.jp/tutorial/svelte/adding-parameters-to-actions" }, { "source": "/tutorial/tippy.js", - "destination": "https://svelte.dev/tutorial/svelte/tippy.js" + "destination": "https://svelte.jp/tutorial/svelte/tippy.js" }, { "source": "/tutorial/contenteditable-bindings", - "destination": "https://svelte.dev/tutorial/svelte/contenteditable-bindings" + "destination": "https://svelte.jp/tutorial/svelte/contenteditable-bindings" }, { "source": "/tutorial/each-block-bindings", - "destination": "https://svelte.dev/tutorial/svelte/each-block-bindings" + "destination": "https://svelte.jp/tutorial/svelte/each-block-bindings" }, { "source": "/tutorial/media-elements", - "destination": "https://svelte.dev/tutorial/svelte/media-elements" + "destination": "https://svelte.jp/tutorial/svelte/media-elements" }, { "source": "/tutorial/dimensions", - "destination": "https://svelte.dev/tutorial/svelte/dimensions" + "destination": "https://svelte.jp/tutorial/svelte/dimensions" }, { "source": "/tutorial/bind-this", - "destination": "https://svelte.dev/tutorial/svelte/bind-this" + "destination": "https://svelte.jp/tutorial/svelte/bind-this" }, { "source": "/tutorial/component-bindings", - "destination": "https://svelte.dev/tutorial/svelte/component-bindings" + "destination": "https://svelte.jp/tutorial/svelte/component-bindings" }, { "source": "/tutorial/component-this", - "destination": "https://svelte.dev/tutorial/svelte/component-this" + "destination": "https://svelte.jp/tutorial/svelte/component-this" }, { "source": "/tutorial/classes", - "destination": "https://svelte.dev/tutorial/svelte/classes" + "destination": "https://svelte.jp/tutorial/svelte/classes" }, { "source": "/tutorial/class-shorthand", - "destination": "https://svelte.dev/tutorial/svelte/class-shorthand" + "destination": "https://svelte.jp/tutorial/svelte/class-shorthand" }, { "source": "/tutorial/styles", - "destination": "https://svelte.dev/tutorial/svelte/styles" + "destination": "https://svelte.jp/tutorial/svelte/styles" }, { "source": "/tutorial/component-styles", - "destination": "https://svelte.dev/tutorial/svelte/component-styles" + "destination": "https://svelte.jp/tutorial/svelte/component-styles" }, { "source": "/tutorial/slots", - "destination": "https://svelte.dev/docs/svelte/legacy-slots" + "destination": "https://svelte.jp/docs/svelte/legacy-slots" }, { "source": "/tutorial/named-slots", - "destination": "https://svelte.dev/docs/svelte/legacy-slots" + "destination": "https://svelte.jp/docs/svelte/legacy-slots" }, { "source": "/tutorial/slot-fallbacks", - "destination": "https://svelte.dev/docs/svelte/legacy-slots" + "destination": "https://svelte.jp/docs/svelte/legacy-slots" }, { "source": "/tutorial/slot-props", - "destination": "https://svelte.dev/docs/svelte/legacy-slots" + "destination": "https://svelte.jp/docs/svelte/legacy-slots" }, { "source": "/tutorial/optional-slots", - "destination": "https://svelte.dev/docs/svelte/legacy-$slots" + "destination": "https://svelte.jp/docs/svelte/legacy-$slots" }, { "source": "/tutorial/context-api", - "destination": "https://svelte.dev/tutorial/svelte/context-api" + "destination": "https://svelte.jp/tutorial/svelte/context-api" }, { "source": "/tutorial/svelte-self", - "destination": "https://svelte.dev/docs/svelte/legacy-svelte-self" + "destination": "https://svelte.jp/docs/svelte/legacy-svelte-self" }, { "source": "/tutorial/svelte-component", - "destination": "https://svelte.dev/docs/svelte/legacy-svelte-component" + "destination": "https://svelte.jp/docs/svelte/legacy-svelte-component" }, { "source": "/tutorial/svelte-element", - "destination": "https://svelte.dev/tutorial/svelte/svelte-element" + "destination": "https://svelte.jp/tutorial/svelte/svelte-element" }, { "source": "/tutorial/svelte-window", - "destination": "https://svelte.dev/tutorial/svelte/svelte-window" + "destination": "https://svelte.jp/tutorial/svelte/svelte-window" }, { "source": "/tutorial/svelte-window-bindings", - "destination": "https://svelte.dev/tutorial/svelte/svelte-window-bindings" + "destination": "https://svelte.jp/tutorial/svelte/svelte-window-bindings" }, { "source": "/tutorial/svelte-body", - "destination": "https://svelte.dev/tutorial/svelte/svelte-body" + "destination": "https://svelte.jp/tutorial/svelte/svelte-body" }, { "source": "/tutorial/svelte-document", - "destination": "https://svelte.dev/tutorial/svelte/svelte-document" + "destination": "https://svelte.jp/tutorial/svelte/svelte-document" }, { "source": "/tutorial/svelte-head", - "destination": "https://svelte.dev/tutorial/svelte/svelte-head" + "destination": "https://svelte.jp/tutorial/svelte/svelte-head" }, { "source": "/tutorial/svelte-options", - "destination": "https://svelte.dev/docs/svelte/svelte-options" + "destination": "https://svelte.jp/docs/svelte/svelte-options" }, { "source": "/tutorial/svelte-fragment", - "destination": "https://svelte.dev/docs/svelte/legacy-svelte-fragment" + "destination": "https://svelte.jp/docs/svelte/legacy-svelte-fragment" }, { "source": "/tutorial/sharing-code", - "destination": "https://svelte.dev/tutorial/svelte/sharing-code" + "destination": "https://svelte.jp/tutorial/svelte/sharing-code" }, { "source": "/tutorial/module-exports", - "destination": "https://svelte.dev/tutorial/svelte/module-exports" + "destination": "https://svelte.jp/tutorial/svelte/module-exports" }, { "source": "/tutorial/debug", - "destination": "https://svelte.dev/docs/svelte/@debug" + "destination": "https://svelte.jp/docs/svelte/@debug" }, { "source": "/tutorial/congratulations", - "destination": "https://svelte.dev/tutorial/svelte/congratulations" + "destination": "https://svelte.jp/tutorial/svelte/congratulations" }, { "source": "/tutorial/introducing-sveltekit", - "destination": "https://svelte.dev/tutorial/kit/introducing-sveltekit" + "destination": "https://svelte.jp/tutorial/kit/introducing-sveltekit" }, { "source": "/tutorial/pages", - "destination": "https://svelte.dev/tutorial/kit/pages" + "destination": "https://svelte.jp/tutorial/kit/pages" }, { "source": "/tutorial/layouts", - "destination": "https://svelte.dev/tutorial/kit/layouts" + "destination": "https://svelte.jp/tutorial/kit/layouts" }, { "source": "/tutorial/params", - "destination": "https://svelte.dev/tutorial/kit/params" + "destination": "https://svelte.jp/tutorial/kit/params" }, { "source": "/tutorial/page-data", - "destination": "https://svelte.dev/tutorial/kit/page-data" + "destination": "https://svelte.jp/tutorial/kit/page-data" }, { "source": "/tutorial/layout-data", - "destination": "https://svelte.dev/tutorial/kit/layout-data" + "destination": "https://svelte.jp/tutorial/kit/layout-data" }, { "source": "/tutorial/headers", - "destination": "https://svelte.dev/tutorial/kit/headers" + "destination": "https://svelte.jp/tutorial/kit/headers" }, { "source": "/tutorial/cookies", - "destination": "https://svelte.dev/tutorial/kit/cookies" + "destination": "https://svelte.jp/tutorial/kit/cookies" }, { "source": "/tutorial/lib", - "destination": "https://svelte.dev/tutorial/kit/lib" + "destination": "https://svelte.jp/tutorial/kit/lib" }, { "source": "/tutorial/the-form-element", - "destination": "https://svelte.dev/tutorial/kit/the-form-element" + "destination": "https://svelte.jp/tutorial/kit/the-form-element" }, { "source": "/tutorial/named-form-actions", - "destination": "https://svelte.dev/tutorial/kit/named-form-actions" + "destination": "https://svelte.jp/tutorial/kit/named-form-actions" }, { "source": "/tutorial/form-validation", - "destination": "https://svelte.dev/tutorial/kit/form-validation" + "destination": "https://svelte.jp/tutorial/kit/form-validation" }, { "source": "/tutorial/progressive-enhancement", - "destination": "https://svelte.dev/tutorial/kit/progressive-enhancement" + "destination": "https://svelte.jp/tutorial/kit/progressive-enhancement" }, { "source": "/tutorial/customizing-use-enhance", - "destination": "https://svelte.dev/tutorial/kit/customizing-use-enhance" + "destination": "https://svelte.jp/tutorial/kit/customizing-use-enhance" }, { "source": "/tutorial/get-handlers", - "destination": "https://svelte.dev/tutorial/kit/get-handlers" + "destination": "https://svelte.jp/tutorial/kit/get-handlers" }, { "source": "/tutorial/post-handlers", - "destination": "https://svelte.dev/tutorial/kit/post-handlers" + "destination": "https://svelte.jp/tutorial/kit/post-handlers" }, { "source": "/tutorial/other-handlers", - "destination": "https://svelte.dev/tutorial/kit/other-handlers" + "destination": "https://svelte.jp/tutorial/kit/other-handlers" }, { "source": "/tutorial/page-store", - "destination": "https://svelte.dev/tutorial/kit/page-store" + "destination": "https://svelte.jp/tutorial/kit/page-store" }, { "source": "/tutorial/navigating-store", - "destination": "https://svelte.dev/tutorial/kit/navigating-store" + "destination": "https://svelte.jp/tutorial/kit/navigating-store" }, { "source": "/tutorial/updated-store", - "destination": "https://svelte.dev/tutorial/kit/updated-store" + "destination": "https://svelte.jp/tutorial/kit/updated-store" }, { "source": "/tutorial/error-basics", - "destination": "https://svelte.dev/tutorial/kit/error-basics" + "destination": "https://svelte.jp/tutorial/kit/error-basics" }, { "source": "/tutorial/error-pages", - "destination": "https://svelte.dev/tutorial/kit/error-pages" + "destination": "https://svelte.jp/tutorial/kit/error-pages" }, { "source": "/tutorial/fallback-errors", - "destination": "https://svelte.dev/tutorial/kit/fallback-errors" + "destination": "https://svelte.jp/tutorial/kit/fallback-errors" }, { "source": "/tutorial/redirects", - "destination": "https://svelte.dev/tutorial/kit/redirects" + "destination": "https://svelte.jp/tutorial/kit/redirects" }, { "source": "/tutorial/handle", - "destination": "https://svelte.dev/tutorial/kit/handle" + "destination": "https://svelte.jp/tutorial/kit/handle" }, { "source": "/tutorial/event", - "destination": "https://svelte.dev/tutorial/kit/event" + "destination": "https://svelte.jp/tutorial/kit/event" }, { "source": "/tutorial/handlefetch", - "destination": "https://svelte.dev/tutorial/kit/handlefetch" + "destination": "https://svelte.jp/tutorial/kit/handlefetch" }, { "source": "/tutorial/handleerror", - "destination": "https://svelte.dev/tutorial/kit/handleerror" + "destination": "https://svelte.jp/tutorial/kit/handleerror" }, { "source": "/tutorial/page-options", - "destination": "https://svelte.dev/tutorial/kit/page-options" + "destination": "https://svelte.jp/tutorial/kit/page-options" }, { "source": "/tutorial/ssr", - "destination": "https://svelte.dev/tutorial/kit/ssr" + "destination": "https://svelte.jp/tutorial/kit/ssr" }, { "source": "/tutorial/csr", - "destination": "https://svelte.dev/tutorial/kit/csr" + "destination": "https://svelte.jp/tutorial/kit/csr" }, { "source": "/tutorial/prerender", - "destination": "https://svelte.dev/tutorial/kit/prerender" + "destination": "https://svelte.jp/tutorial/kit/prerender" }, { "source": "/tutorial/trailingslash", - "destination": "https://svelte.dev/tutorial/kit/trailingslash" + "destination": "https://svelte.jp/tutorial/kit/trailingslash" }, { "source": "/tutorial/preload", - "destination": "https://svelte.dev/tutorial/kit/preload" + "destination": "https://svelte.jp/tutorial/kit/preload" }, { "source": "/tutorial/reload", - "destination": "https://svelte.dev/tutorial/kit/reload" + "destination": "https://svelte.jp/tutorial/kit/reload" }, { "source": "/tutorial/optional-params", - "destination": "https://svelte.dev/tutorial/kit/optional-params" + "destination": "https://svelte.jp/tutorial/kit/optional-params" }, { "source": "/tutorial/rest-params", - "destination": "https://svelte.dev/tutorial/kit/rest-params" + "destination": "https://svelte.jp/tutorial/kit/rest-params" }, { "source": "/tutorial/param-matchers", - "destination": "https://svelte.dev/tutorial/kit/param-matchers" + "destination": "https://svelte.jp/tutorial/kit/param-matchers" }, { "source": "/tutorial/route-groups", - "destination": "https://svelte.dev/tutorial/kit/route-groups" + "destination": "https://svelte.jp/tutorial/kit/route-groups" }, { "source": "/tutorial/breaking-out-of-layouts", - "destination": "https://svelte.dev/tutorial/kit/breaking-out-of-layouts" + "destination": "https://svelte.jp/tutorial/kit/breaking-out-of-layouts" }, { "source": "/tutorial/universal-load-functions", - "destination": "https://svelte.dev/tutorial/kit/universal-load-functions" + "destination": "https://svelte.jp/tutorial/kit/universal-load-functions" }, { "source": "/tutorial/using-both-load-functions", - "destination": "https://svelte.dev/tutorial/kit/using-both-load-functions" + "destination": "https://svelte.jp/tutorial/kit/using-both-load-functions" }, { "source": "/tutorial/await-parent", - "destination": "https://svelte.dev/tutorial/kit/await-parent" + "destination": "https://svelte.jp/tutorial/kit/await-parent" }, { "source": "/tutorial/invalidation", - "destination": "https://svelte.dev/tutorial/kit/invalidation" + "destination": "https://svelte.jp/tutorial/kit/invalidation" }, { "source": "/tutorial/custom-dependencies", - "destination": "https://svelte.dev/tutorial/kit/custom-dependencies" + "destination": "https://svelte.jp/tutorial/kit/custom-dependencies" }, { "source": "/tutorial/invalidate-all", - "destination": "https://svelte.dev/tutorial/kit/invalidate-all" + "destination": "https://svelte.jp/tutorial/kit/invalidate-all" }, { "source": "/tutorial/env-static-private", - "destination": "https://svelte.dev/tutorial/kit/env-static-private" + "destination": "https://svelte.jp/tutorial/kit/env-static-private" }, { "source": "/tutorial/env-dynamic-private", - "destination": "https://svelte.dev/tutorial/kit/env-dynamic-private" + "destination": "https://svelte.jp/tutorial/kit/env-dynamic-private" }, { "source": "/tutorial/env-static-public", - "destination": "https://svelte.dev/tutorial/kit/env-static-public" + "destination": "https://svelte.jp/tutorial/kit/env-static-public" }, { "source": "/tutorial/env-dynamic-public", - "destination": "https://svelte.dev/tutorial/kit/env-dynamic-public" + "destination": "https://svelte.jp/tutorial/kit/env-dynamic-public" }, { "source": "/tutorial/next-steps", - "destination": "https://svelte.dev/tutorial/kit/next-steps" + "destination": "https://svelte.jp/tutorial/kit/next-steps" }, { "source": "/", - "destination": "https://svelte.dev/tutorial" + "destination": "https://svelte.jp/tutorial" }, { "source": "/(.*)", - "destination": "https://svelte.dev/$1" + "destination": "https://svelte.jp/$1" } ] } diff --git a/apps/svelte.dev/content/blog/2016-11-26-frameworks-without-the-framework.md b/apps/svelte.dev/content/blog/2016-11-26-frameworks-without-the-framework.md index 7756f3135a..ea64857d28 100644 --- a/apps/svelte.dev/content/blog/2016-11-26-frameworks-without-the-framework.md +++ b/apps/svelte.dev/content/blog/2016-11-26-frameworks-without-the-framework.md @@ -1,51 +1,51 @@ --- -title: "Frameworks without the framework: why didn't we think of this sooner?" -description: You can't write serious applications in vanilla JavaScript without hitting a complexity wall. But a compiler can do it for you. +title: "フレームワークの無いフレームワーク: なぜもっと早く思いつかなかったのか" +description: 純粋なJavaScriptでは、複雑さの壁にぶつかることなく本格的なアプリケーションを書くことはできません。しかしコンパイラならそれができます。 author: Rich Harris authorURL: https://bsky.app/profile/rich-harris.dev --- -> Wait, this new framework has a _runtime_? Ugh. Thanks, I'll pass. +> 待って、この新しいフレームワークには _ランタイム_ があるの? うーん。ありがとう、やめておくよ。 > **– front end developers in 2018** -We're shipping too much code to our users. Like a lot of front end developers, I've been in denial about that fact, thinking that it was fine to serve 100kb of JavaScript on page load – just use [one less .jpg!](https://twitter.com/miketaylr/status/227056824275333120) – and that what _really_ mattered was performance once your app was already interactive. +私たちはあまりに多くのコードをユーザーに配布しています。多くのフロントエンド開発者と同じように私もこの事実を否定し、ページロードの際に 100kb の JavaScript を配布しても問題ないと考えていました。[.jpg を1つ減らせば](https://twitter.com/miketaylr/status/227056824275333120) 良いだけだと。そして _本当に_ 重要なのはアプリケーションがインタラクティブになった後のパフォーマンスだと考えていました。 -But I was wrong. 100kb of .js isn't equivalent to 100kb of .jpg. It's not just the network time that'll kill your app's startup performance, but the time spent parsing and evaluating your script, during which time the browser becomes completely unresponsive. On mobile, those milliseconds rack up very quickly. +しかし、私は間違っていました。100kb の .js は 100kb の .jpg と同じではありません。アプリの起動時のパフォーマンスを低下させるのはネットワークの時間だけではありません。script の解析と評価にも時間がかかり、その間ブラウザーは完全に無反応になります。モバイルでは、このミリ秒単位の時間があっという間に積み上がります。 -If you're not convinced that this is a problem, follow [Alex Russell](https://bsky.app/profile/infrequently.org) on BlueSky. Alex [hasn't been making many friends in the framework community lately](https://twitter.com/slightlylate/status/728355959022587905), but he's not wrong. But the proposed alternative to using frameworks like Angular, React and Ember – [Polymer](https://www.polymer-project.org/1.0/) – hasn't yet gained traction in the front end world, and it's certainly not for a lack of marketing. +これが問題であることに納得できないなら、Twitter で [Alex Russell](https://bsky.app/profile/infrequently.org) をフォローしてください。Alex は [最近、フレームワークコミュニティで多くの友人を作ろうとしませんが](https://twitter.com/slightlylate/status/728355959022587905)、彼は間違っていません。しかし、Angular、React、Ember などのフレームワークの代替として提案されている [Polymer](https://www.polymer-project.org/1.0/) は、フロントエンドの世界ではまだ普及していませんし、それは決してマーケティングが不足しているからではありません。 -Perhaps we need to rethink the whole thing. +おそらく、全てを再考する必要があります。 -## What problem do frameworks _really_ solve? +## フレームワークが _本当に_ 解決すること -The common view is that frameworks make it easier to manage the complexity of your code: the framework abstracts away all the fussy implementation details with techniques like virtual DOM diffing. But that's not really true. At best, frameworks _move the complexity around_, away from code that you had to write and into code you didn't. +フレームワークはコードの複雑さを管理しやすくする、というのが一般的な認識です。フレームワークは仮想DOMの差分検出などの技術によって面倒な実装の詳細を抽象化する、というものです。しかし、実際にはそうではありません。せいぜい、あなたが書かなければならないコードからあなたが書いていないコードに _複雑さを移動させる_ だけです。 -Instead, the reason that ideas like React are so wildly and deservedly successful is that they make it easier to manage the complexity of your _concepts_. Frameworks are primarily a tool for structuring your thoughts, not your code. +むしろ、React のようなアイデアがこれほど成功した理由は、 _コンセプト_ の複雑さを管理しやすくしているからです。フレームワークはコードではなく思考を構造化するためのツールです。 -Given that, what if the framework _didn't actually run in the browser_? What if, instead, it converted your application into pure vanilla JavaScript, just like Babel converts ES2016+ to ES5? You'd pay no upfront cost of shipping a hefty runtime, and your app would get seriously fast, because there'd be no layers of abstraction between your app and the browser. +そう考えると、もしそのフレームワークが _実際にはブラウザーで動かない_ としたらどうでしょうか? 代わりに、Babel が ES2016+ から ES5 に変換するように、アプリケーションを純粋なJavaScriptに変換するとしたら? 重たいランタイムを配布するための初期コストを支払うことはなく、アプリは本当に高速になります。アプリとブラウザの間の抽象レイヤーがなくなるからです。 ## Introducing Svelte -Svelte is a new framework that does exactly that. You write your components using HTML, CSS and JavaScript (plus a few extra bits you can [learn in under 5 minutes](https://v2.svelte.dev/guide)), and during your build process Svelte compiles them into tiny standalone JavaScript modules. By statically analysing the component template, we can make sure that the browser does as little work as possible. +Svelte はまさにそれを実現するフレームワークです。HTML、CSS、JavaScript (それと [5分以内に学べる](https://v2.svelte.dev/guide) ちょっとしたこと) でコンポーネントを書き、Svelte がそれをビルドプロセスで小さなスタンドアローンの JavaScript モジュールにコンパイルします。コンポーネントのテンプレートを静的に解析することで、ブラウザーの作業を可能な限り少なくなるようにすることができます。 -The [Svelte implementation of TodoMVC](https://svelte-todomvc.surge.sh/) weighs 3.6kb zipped. For comparison, React plus ReactDOM _without any app code_ weighs about 45kb zipped. It takes about 10x as long for the browser just to evaluate React as it does for Svelte to be up and running with an interactive TodoMVC. +[Svelte による TodoMVC の実装](https://svelte-todomvc.surge.sh/) は 3.6kb (zipped) です。比較として、 _アプリコードを除いた_ React と ReactDOM はおよそ 45kb (zipped) です。ブラウザーが React を評価するのにかかる時間は、Svelteがインタラクティブな TodoMVC を起動して実行するのにかかる時間の約10倍です。 -And once your app _is_ up and running, according to [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark) **Svelte is fast as heck**. It's faster than React. It's faster than Vue. It's faster than Angular, or Ember, or Ractive, or Preact, or Riot, or Mithril. It's competitive with Inferno, which is probably the fastest UI framework in the world, for now, because [Dominic Gannaway](https://bsky.app/profile/trueadm.dev) is a wizard. (Svelte is slower at removing elements. We're [working on it](https://github.com/sveltejs/svelte/issues/26).) +そして [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark) によれば、アプリが起動して実行されると **Svelte はとてもつもなく高速です**。React よりも速いです。Vue よりも速いです。Angular、Ember、Ractive、Preact、Riot、Mithrilよりも速いです。今のところ、おそらく世界で最も高速な UI フレームワークである Inferno ([Dominic Gannaway](https://bsky.app/profile/trueadm.dev) は魔法使い(a wizard)なので) に匹敵します。(Svelte は要素の削除が遅いですが、[それについては取り組んでいます](https://github.com/sveltejs/svelte/issues/26)) -It's basically as fast as vanilla JS, which makes sense because it _is_ vanilla JS – just vanilla JS that you didn't have to write. +基本的には純粋な JS と同じくらい速いです。実際、それは _純粋な JS なので_ 当然です。ただ、純粋な JS を書く必要がないというだけです。 -## But that's not the important thing +## 本当に重要なことは -Well, it _is_ important – performance matters a great deal. What's really exciting about this approach, though, is that we can finally solve some of the thorniest problems in web development. +ええ、パフォーマンスはとても重要です。しかし、このアプローチの本当にエキサイティングなところは、Web 開発におけるいくつかの厄介な問題をついに解決できることです。 -Consider interoperability. Want to `npm install cool-calendar-widget` and use it in your app? Previously, you could only do that if you were already using (a correct version of) the framework that the widget was designed for – if `cool-calendar-widget` was built in React and you're using Angular then, well, hard cheese. But if the widget author used Svelte, apps that use it can be built using whatever technology you like. (On the TODO list: a way to convert Svelte components into web components.) +相互運用性について考えてみてください。`npm install cool-calendar-widget` を実行してアプリで使いたいですか? これまでは、そのウィジェットがそのフレームワーク向けにデザインされていて、あなたがそのフレームワーク(の正しいバージョン)を使っているときに限りそれが可能でした。もし `cool-calendar-widget` が React で作られており、あなたが Angular を使っていたら、まあ、残念でしたね。しかし、もしそのウィジェットの作者が Svelte を使用した場合、そのウィジェットを使用するアプリを好きなテクノロジーで構築することができます。(TODOリスト : Svelte コンポーネントを Web Components に変換する方法) -Or [code splitting](https://twitter.com/samccone/status/797528710085652480). It's a great idea (only load the code the user needs for the initial view, then get the rest later), but there's a problem – even if you only initially serve one React component instead of 100, _you still have to serve React itself_. With Svelte, code splitting can be much more effective, because the framework is embedded in the component, and the component is tiny. +他には、[コード分割](https://twitter.com/samccone/status/797528710085652480) があります。これは素晴らしいアイデア (初期表示に必要なコードだけをロードし、残りは後で取得する) ですが、問題があります。100個の React コンポーネントではなく、最初に1個の React コンポーネントを配布するだけでも、 _React自体を配布しなければなりません_ 。Svelteでは、フレームワークはコンポーネントに埋め込まれており、そのコンポーネントは小さいため、コード分割がより効果的です。 -Finally, something I've wrestled with a great deal as an open source maintainer: your users always want _their_ features prioritised, and underestimate the cost of those features to people who don't need them. A framework author must always balance the long-term health of the project with the desire to meet their users' needs. That's incredibly difficult, because it's hard to anticipate – much less articulate – the consequences of incremental bloat, and it takes serious soft skills to tell people (who may have been enthusiastically evangelising your tool up to that point) that their feature isn't important enough. But with an approach like Svelte's, many features can be added with absolutely no cost to people who don't use them, because the code that implements those features just doesn't get generated by the compiler if it's unnecessary. +最後に、オープンソースのメンテナーとして悪戦苦闘してきたこと。ユーザーは常に自分の機能を優先してほしいし、その機能を必要としていない人に対してその機能のコストを低く見積もります。フレームワークの作者は、プロジェクトの長期的な健全性と、ユーザーのニーズを満たしたいという欲求との間でバランスを常に取り続けなければなりません。これはとてつもなく難しいことです。なぜなら、少しずつ大きくなっていく成果・結果を予測したりすることはできないですし、ましてや明確にすることは不可能です。また、(それまで熱狂的にツールを伝道してきた)人たちに、それらの機能に重要な部分が足りていないと伝えるには本格的なソフトスキルが必要です。しかし Svelte のようなアプローチでは、使用していない機能のコードはコンパイラによって生成されないため、多くの機能を追加しても、その機能を必要としていない人にそのコストを与えることは全くありません。 -## We're just getting started +## まだ始まったばかり -Svelte is very new. There's a lot of work still left to do – creating build tool integrations, adding a server-side renderer, hot reloading, transitions, more documentation and examples, starter kits, and so on. +Svelteは非常に新しいです。ビルドツールのインテグレーション作成、サーバーサイドレンダラー、ホットリロード、トランジション、ドキュメントやサンプルの追加、スターターキットなど、まだまだやるべきことがたくさんあります。 -But you can already build rich components with it, which is why we've gone straight to a stable 1.0.0 release. [Read the guide](https://v2.svelte.dev/guide), [try it out in the REPL](/repl), and head over to [GitHub](https://github.com/sveltejs/svelte) to help kickstart the next era of front end development. +しかし、すでにリッチなコンポーネントを構築することができます。それが stable な 1.0.0 のリリースに至った理由です。[ガイドを読み](https://v2.svelte.dev/guide)、[REPL で試して](/repl)、そして [GitHub](https://github.com/sveltejs/svelte) にアクセスして、次世代のフロントエンド開発をスタートしてください。 diff --git a/apps/svelte.dev/content/blog/2017-12-31-sapper-towards-the-ideal-web-app-framework.md b/apps/svelte.dev/content/blog/2017-12-31-sapper-towards-the-ideal-web-app-framework.md index 228c149ddd..224c371ecd 100644 --- a/apps/svelte.dev/content/blog/2017-12-31-sapper-towards-the-ideal-web-app-framework.md +++ b/apps/svelte.dev/content/blog/2017-12-31-sapper-towards-the-ideal-web-app-framework.md @@ -1,80 +1,80 @@ --- -title: 'Sapper: Towards the ideal web app framework' -description: Taking the next-plus-one step +title: "Sapper: 理想の Web アプリケーションフレームワークを目指して" +description: 次の一歩を踏み出す author: Rich Harris authorURL: https://bsky.app/profile/rich-harris.dev --- -> Quickstart for the impatient: [the Sapper docs](https://sapper.svelte.dev), and the [starter template](https://github.com/sveltejs/sapper-template) +> せっかちな人のためのクイックスタート: [Sapper のドキュメント](https://sapper.svelte.dev)、[スターターテンプレート](https://github.com/sveltejs/sapper-template) -If you had to list the characteristics of the perfect Node.js web application framework, you'd probably come up with something like this: +もし完璧な Node.js の Web アプリケーションフレームワークの特徴を挙げるとしたら、次のようなものを思いつくでしょう: -1. It should do server-side rendering, for fast initial loads and no caveats around SEO -2. As a corollary, your app's codebase should be universal — write once for server _and_ client -3. The client-side app should _hydrate_ the server-rendered HTML, attaching event listeners (and so on) to existing elements rather than re-rendering them -4. Navigating to subsequent pages should be instantaneous -5. Offline, and other Progressive Web App characteristics, must be supported out of the box -6. Only the JavaScript and CSS required for the first page should load initially. That means the framework should do automatic code-splitting at the route level, and support dynamic `import(...)` for more granular manual control -7. No compromise on performance -8. First-rate developer experience, with hot module reloading and all the trimmings -9. The resulting codebase should be easy to grok and maintain -10. It should be possible to understand and customise every aspect of the system — no webpack configs locked up in the framework, and as little hidden 'plumbing' as possible -11. Learning the entire framework in under an hour should be easy, and not just for experienced developers +1. 最初の読み込みの高速化や SEO 対策に支障をきたさないために、サーバーサイドレンダリングを行う +2. 当然の結果として、アプリケーションのコードベースは普遍的である — サーバーとクライアント _共通_ で1度だけコードを書く +3. クライアントサイドのアプリは、サーバーでレンダリングされた HTML を再レンダリングすると言うより既存の要素にイベントリスナ(などなど)をアタッチして _ハイドレート_ する +4. 瞬時に次のページに移動できる +5. オフラインや、その他のプログレッシブウェブアプリの特徴をすぐにサポートしている +6. 最初のページに必要な JavaScript と CSS のみが最初に読み込まれる。 つまり、フレームワークはルートレベルで自動的にコード分割を行い、より細かい手動制御のために動的な `import(...)` をサポートしている +7. パフォーマンスに妥協がない +8. ホットモジュールリローディングやその他痒い所に手が届く様々な機能など、最高の開発環境を提供している +9. 出来上がったコードベースは、理解しやすくメンテナンス性が高い +10. システムのあらゆる側面を理解し、カスタマイズをすることができる — webpack の設定をフレームワークの中に閉じ込めず、できるだけ隠された「配管」を少なくしている +11. フレームワーク全体を1時間以内に学習することは、経験豊富な開発者でなくても簡単にできる -[Next.js](https://github.com/zeit/next.js) is close to this ideal. If you haven't encountered it yet, I strongly recommend going through the tutorials at [learnnextjs.com](https://learnnextjs.com). Next introduced a brilliant idea: all the pages of your app are files in a `your-project/pages` directory, and each of those files is just a React component. +[Next.js](https://github.com/zeit/next.js) はこの理想に近いです。 もし Next.js に出会ったことがないなら、 [learnnextjs.com](https://learnnextjs.com) でチュートリアルを見てみることを強くおすすめします。 Next は素晴らしいアイディアをご紹介します: あなたのアプリケーションの全ページは `your-project/pages` ディレクトリにあるファイルで、それらのファイルのそれぞれが React のコンポーネントです。 -Everything else flows from that breakthrough design decision. Finding the code responsible for a given page is easy, because you can just look at the filesystem rather than playing 'guess the component name'. Project structure bikeshedding is a thing of the past. And the combination of SSR (server-side rendering) and code-splitting — something the React Router team [gave up on](https://reacttraining.com/react-router/web/guides/code-splitting), declaring 'Godspeed those who attempt the server-rendered, code-split apps' — is trivial. +それ以外のことについては、この画期的な設計の方針に基づいています。「コンポーネント名推測ゲーム」をして遊ぶわけではなくファイルシステムを見るだけでいいので、特定のページを受け持つコードを見つけるのは簡単です。 プロジェクトの構造のことで無駄に細かいことを考える必要がある時代は終わりました。 また、 SSR(サーバーサイドレンダリング)とコード分割の組み合わせは (React Router チームが「サーバーでレンダリングされ、コード分割されたアプリに挑戦する人たちに神の祝福あれ」と言って[断念した](https://reacttraining.com/react-router/web/guides/code-splitting)ものではありますが) 些細なことです。 -But it's not perfect. As churlish as it might be to list the flaws in something _so, so good_, there are some: +それでも、完璧なわけではありません。 _とても素晴らしいもの_ の粗探しをするのは無粋かもしれませんが、いくつか挙げられます: -- Next uses something called 'route masking' to create nice URLs (e.g. `/blog/hello-world` instead of `/post?slug=hello-world`). This undermines the guarantee about directory structure corresponding to app structure, and forces you to maintain configuration that translates between the two forms -- All your routes are assumed to be universal 'pages'. But it's very common to need routes that only render on the server, such as a 301 redirect or an API endpoint that serves the data for your pages, and Next doesn't have a great solution for this. You can add logic to your `server.js` file to handle these cases, but it feels at odds with the declarative approach taken for pages -- To use the client-side router, links can't be standard `` tags. Instead, you have to use framework-specific `` components, which is impossible in the markdown content for a blog post such as this one, for example +- Next は「ルートマスキング」と呼ばれる機能を使ってイケてる URL を生成します (例えば `/post?slug=hello-world` の代わりに `/blog/hello-world`)。 これは、アプリケーションの構造に対するディレクトリ構造の保証を損なうものであり、2つの構造の形式の間で変換する設定を維持する必要があります。 +- 全てのルーティングは普遍的な「ページ」であると想定されます。 しかしながら、 301 redirect やページにデータを提供する API エンドポイントのような、サーバーでのみレンダリングされるルーティングが必要になることは一般的にあることで、 Next はこれに関して良い解決策を持っていません。 こういったケースを処理するために `server.js` ファイルにロジックを追加することはできますが、これはページの宣言的なアプローチに相反するものです。 +- クライアントサイドのルーティングを利用する場合、リンクに標準的な `` タグを使うことができません。 代わりに、例えば本ブログ記事のようなマークダウンコンテンツでは利用不可能な、フレームワーク固有の `` コンポーネントを使わなければいけません -The real problem, though, is that all that goodness comes for a price. The simplest possible Next app — a single 'hello world' page that renders some static text — involves 66kb of gzipped JavaScript. Unzipped, it's 204kb, which is a non-trivial amount of code for a mobile device to parse at a time when performance is a critical factor determining whether or not your users will stick around. And that's the _baseline_. +しかしながら、実際の問題として、これらのような良い機能には代償が伴います。 もっともシンプルな Next のアプリケーションは、 — 静的なテキストを表示する「hello world」ページですが — 66kb の 圧縮された JavaScript を含みます。 解凍すると 204kb になりますが、これは、パフォーマンスがユーザーの定着率を左右する重要な要素であるときに、モバイルデバイスが一度に解析するには大きく問題のあるコードの量です。 そして、これが _ベースライン_ になります。 -We can do better! +私たちなら、もっとより良くできます! -## The compiler-as-framework paradigm shift +## フレームワークパラダイムシフトとしてのコンパイラ -[Svelte introduced a radical idea](/blog/frameworks-without-the-framework): what if your UI framework wasn't a framework at all, but a compiler that turned your components into standalone JavaScript modules? Instead of using a library like React or Vue, which knows nothing about your app and must therefore be a one-size-fits-all solution, we can ship highly-optimised vanilla JavaScript. Just the code your app needs, and without the memory and performance overhead of solutions based on a virtual DOM. +[Svelte は根本的な思想を紹介しています](/blog/frameworks-without-the-framework): UIフレークワークがフレームワークではなく、コンポーネントをスタンドアロンな JavaScript モジュールに変換するコンパイラだったらどうですか?React や Vue のような、アプリのことを何も知らず無難なソリューションにならざるを得ないライブラリを使う代わりに、私たちは高度に最適化された純粋な JavaScript を送り出すことができます。 アプリケーションに必要なコードだけで、仮想DOMをベースとしたソリューションのようなメモリやパフォーマンスのオーバーヘッドはありません。 -The JavaScript world is [moving towards this model](https://tomdale.net/2017/09/compilers-are-the-new-frameworks/). [Stencil](https://stenciljs.com), a Svelte-inspired framework from the Ionic team, compiles to web components. [Glimmer](https://glimmerjs.com) _doesn't_ compile to standalone JavaScript (the pros and cons of which deserve a separate blog post), but the team is doing some fascinating research around compiling templates to bytecode. (React is [getting in on the action](https://twitter.com/trueadm/status/944908776896978946), though their current research focuses on optimising your JSX app code, which is arguably more similar to the ahead-of-time optimisations that Angular, Ractive and Vue have been doing for a few years.) +JavaScript の世界は [このモデルに向かっています](https://tomdale.net/2017/09/compilers-are-the-new-frameworks/)。 [Stencil](https://stenciljs.com) は Ionic のチームによる Svelte からインスピレーションを受けたフレームワークで、 Web コンポーネントにコンパイルされます。 [Glimmer](https://glimmerjs.com) は スタンドアロンな JavaScript にコンパイル _するわけではありませんが_ (その長所と短所については、別のブログの記事にしたいと思います)、このチームはテンプレートをバイトコードにコンパイルすることについての興味深い研究を行なっています。 (React は [このような動きに足を踏み入れていますが](https://twitter.com/trueadm/status/944908776896978946)、彼らの現在の研究は JSX で書かれたアプリケーションのコードを最適化することに焦点を当てており、これは間違いなく Angular、 Ractive、 そして Vue がここ数年で行なっている事前最適化によく似たものです) -What happens if we use the new model as a starting point? +私たちがこの新しいモデルを出発点として用いるとどうなるのでしょうか? -## Introducing Sapper +## Sapper の紹介 - + -[Sapper](https://sapper.svelte.dev) is the answer to that question. **Sapper is a Next.js-style framework that aims to meet the eleven criteria at the top of this article while dramatically reducing the amount of code that gets sent to the browser.** It's implemented as Express-compatible middleware, meaning it's easy to understand and customise. +[Sapper](https://sapper.svelte.dev) はその問いへの答えです。 **Sapper は Next.js スタイルのフレームワークで、この記事の上部にある11の基準を満たしつつ、ブラウザに送信されるコードの量を劇的に減らすことを目的としています。** Express と互換性のあるミドルウェアとして実装されているため、理解しやすく、カスタマイズも容易に行えます。 -The same 'hello world' app that took 204kb with React and Next weighs just 7kb with Sapper. That number is likely to fall further in the future as we explore the space of optimisation possibilities, such as not shipping any JavaScript _at all_ for pages that aren't interactive, beyond the tiny Sapper runtime that handles client-side routing. +同じ「hello world」のアプリケーションでも、React や Next では 204kb もあったものが、 Sapper ではたったの 7kb です。 クライアントサイドのルーティングを処理する Sapper のごく僅かなランタイムを除いて、インタラクティブではないページでは _一切の_ JavaScript を読み込まないなどの最適化の可能性を探っていくうちに、将来的にこの数字はさらに小さくなっていくでしょう。 -What about a more 'real world' example? Conveniently, the [RealWorld](https://github.com/gothinkster/realworld) project, which challenges frameworks to develop an implementation of a Medium clone, gives us a way to find out. The [Sapper implementation](https://github.com/sveltejs/realworld) takes 39.6kb (11.8kb zipped) to render an interactive homepage. +さらに、「RealWorld」の例はどうでしょうか? 好都合なことに、 Medium クローンの実装をフレームワークで開発するという [RealWorld](https://github.com/gothinkster/realworld) プロジェクトでは、その結果を知ることができます。 [Sapper での実装](https://github.com/sveltejs/realworld) では、インタラクティブなホームページを表示するのに 39.6kb (zip形式では 11.8kb) かかります。 - + -The entire app costs 132.7kb (39.9kb zipped), which is significantly smaller than the reference React/Redux implementation at 327kb (85.7kb), but even if it was as large it would _feel_ faster because of code-splitting. And that's a crucial point. We're told we need to code-split our apps, but if your app uses a traditional framework like React or Vue then there's a hard lower bound on the size of your initial code-split chunk — the framework itself, which is likely to be a significant portion of your total app size. With the Svelte approach, that's no longer the case. +アプリ全体のコストは 132.7kb (zip形式で 39.9kb) で、リファレンスの React/Redux での実装の 327kb (85.7kb) よりは著しく小さいですが、例え同じくらいの大きさであってもコード分割のおかげで _体感的には_ 速くなっています。そしてこれが重要なポイントです。 アプリケーションではコード分割をする必要があると言われていますが、 React や Vue のような伝統的なフレームワークを利用している場合、最初にコードを分割するチャンクのサイズには厳しい下限があります — フレームワーク自体がアプリ全体のサイズの中で大部分を占めていると考えられるからです。 Svelte のアプローチは、もはやそのようなことはありません。 -But size is only part of the story. Svelte apps are also extremely performant and memory-efficient, and the framework includes powerful features that you would sacrifice if you chose a 'minimal' or 'simple' UI library. +しかしサイズの話は物語の一部に過ぎません。 また、 Svelte アプリケーションはパフォーマンスやメモリ効率が非常に高く、「ミニマル」や「シンプル」なUIライブラリを選択した場合に犠牲にしてしまうような強力な機能がこのフレームワークには含まれています。 -## Trade-offs +## トレードオフ -The biggest drawback for many developers evaluating Sapper would be 'but I like React, and I already know how to use it', which is fair. +多くの開発者が Sapper を評価する際の最大の難点は、「それでも React は好きだし、使い方もすでに知ってるよ」ということでしょうが、それは妥当なことです。 -If you're in that camp, I'd invite you to at least try alternative frameworks. You might be pleasantly surprised! The [Sapper RealWorld](https://github.com/sveltejs/realworld) implementation totals 1,201 lines of source code, compared to 2,377 for the reference implementation, because you're able to express concepts very concisely using Svelte's template syntax (which [takes all of five minutes to master](https://v2.svelte.dev/guide#template-syntax)). You get [scoped CSS](/blog/the-zen-of-just-writing-css), with unused style removal and minification built-in, and you can use preprocessors like LESS if you want. You no longer need to use Babel. SSR is ridiculously fast, because it's just string concatenation. And we recently introduced [svelte/store](https://v2.svelte.dev/guide#state-management), a tiny global store that synchronises state across your component hierarchy with zero boilerplate. The worst that can happen is that you'll end up feeling vindicated! +そんな方々には、ぜひ代替フレームワークを試していただきたいと思います。 嬉しい驚きがあるかも知れません! [Sapper による RealWorld](https://github.com/sveltejs/realworld) の実装ではソースコードの総行数が 1,201 行なのに対し、リファレンスでの実装では 2,377 行となっています。 これは、Svelte のテンプレート構文を使って概念を非常に簡潔に表現できるからで、[5分もあればマスターできます](https://v2.svelte.dev/guide#template-syntax)。 使われていないスタイルの削除と縮小化が組み込まれた[scoped CSS](/blog/the-zen-of-just-writing-css)を取得し、必要に応じて LESS のようなプリプロセッサを使用することができます。 Babel を使用する必要はありません。 SSR は、文字列を連結するだけなのでとてつもなく高速です。 また、最近導入した [svelte/store](https://v2.svelte.dev/guide#state-management)は、コンポーネント階層間で状態を同期させる小さなグローバルストアです。 最悪の場合、自分の正当性が証明されたような気になってしまうかも知れませんね! -But there are trade-offs nonetheless. Some people have a pathological aversion to any form of 'template language', and maybe that applies to you. JSX proponents will clobber you with the 'it's just JavaScript' mantra, and therein lies React's greatest strength, which is that it is infinitely flexible. That flexibility comes with its own set of trade-offs, but we're not here to discuss those. +とは言え、トレードオフもあります。 いかなる「テンプレート言語」にも病的なまでに嫌悪感を抱く人がいますが、もしかしたらあなたも当てはまるかも知れません。 JSX の支持者は「それはただの JavaScript だ」と酷評するでしょうが、そこには React の最大の強みである、無限の柔軟性があるのです。 そのような柔軟性にはトレードオフがつきものですが、ここでそれについて議論するつもりはありません。 -And then there's _ecosystem_. The universe around React in particular — the devtools, editor integrations, ancillary libraries, tutorials, StackOverflow answers, hell, even job opportunities — is unrivalled. While it's true that citing 'ecosystem' as the main reason to choose a tool is a sign that you're stuck on a local maximum, apt to be marooned by the rising waters of progress, it's still a major point in favour of incumbents. +そして、 _エコシステム_ があります。 特に React を取り巻く世界では、開発ツール、統合開発環境、付属ライブラリ、チュートリアル、 StackOverflow の回答、就職の機会に至るまで、他の追随を許さないものとなっています。 確かに、ツールを選ぶ主な理由として「エコシステム」を挙げるのは、無難な位置にとどまってしまっていて進歩の波に取り残されがちであることを示していますが、それでも既存の企業にとっては大きなポイントになります。 -## Roadmap +## ロードマップ -We're not at version 1.0.0 yet, and a few things may change before we get there. Once we do (soon!), there are a lot of exciting possibilities. +まだバージョン 1.0.0 ではありませんし、そこに辿り着くまでにいくつか修正する点があるかも知れません。 それが実現した暁には (もうすぐです!)、ワクワクするようなたくさんの可能性を秘めているでしょう。 -I believe the next frontier of web performance is 'whole-app optimisation'. Currently, Svelte's compiler operates at the component level, but a compiler that understood the boundaries _between_ those components could generate even more efficient code. The React team's [Prepack research](https://twitter.com/trueadm/status/944908776896978946) is predicated on a similar idea, and the Glimmer team is doing some interesting work in this space. Svelte and Sapper are well positioned to take advantage of these ideas. +私は、 Web パフォーマンスにおける次の新天地は「アプリケーション全体の最適化」だと考えています。 現在、 Svelte のコンパイラはコンポーネントレベルで動作していますが、_コンポーネント間_ の境界を解釈することができるコンパイラがあれば、より効率的なコードを生成することができます。 React チームの [Prepack の研究](https://twitter.com/trueadm/status/944908776896978946) も同様の考え方に基づいていますし、 Glimmer チームもこの分野で興味深い研究を行なっています。 Svelte と Sapper はこれらのアイディアを活かすことのできるポジションにいます。 -Speaking of Glimmer, the idea of compiling components to bytecode is one that we'll probably steal in 2018. A framework like Sapper could conceivably determine which compilation mode to use based on the characteristics of your app. It could even serve JavaScript for the initial route for the fastest possible startup time, then lazily serve a bytecode interpreter for subsequent routes, resulting in the optimal combination of startup size and total app size. +Glimmerといえば、コンポーネントをバイトコードにコンパイルするというアイディアは、2018年にはおそらく盗むことになるでしょう。 Sapper のようなフレームワークは、アプリの特性に応じてどのコンパイルモードを使うかを決めることができます 。 初回のルーティングでは JavaScript を提供して起動時間を最短にし、その後のルーティングではバイトコードインタプリタを遅延なく提供することで、起動サイズとアプリ全体のサイズの最適な組み合わせを実現することもできます。 -Mostly, though, we want the direction of Sapper to be determined by its users. If you're the kind of developer who enjoys life on the bleeding edge and would like to help shape the future of how we build web apps, please join us on [GitHub](https://github.com/sveltejs/svelte) and [Discord](/chat). +とは言え、 Sapper の方向性の大部分はユーザーに決めてもらいたいと考えています。あなたが最先端の生活を楽しみ、 Web アプリケーションの構築方法の未来を形作る手助けをしたいと思っている開発者であれば、ぜひ私たちの [GitHub](https://github.com/sveltejs/svelte) や [Discord](/chat) に参加してください。 diff --git a/apps/svelte.dev/content/blog/2018-12-27-virtual-dom-is-pure-overhead.md b/apps/svelte.dev/content/blog/2018-12-27-virtual-dom-is-pure-overhead.md index 9aece76947..a462b534b3 100644 --- a/apps/svelte.dev/content/blog/2018-12-27-virtual-dom-is-pure-overhead.md +++ b/apps/svelte.dev/content/blog/2018-12-27-virtual-dom-is-pure-overhead.md @@ -1,26 +1,30 @@ --- -title: Virtual DOM is pure overhead -description: Let's retire the 'virtual DOM is fast' myth once and for all +title: 仮想DOMは純粋なオーバーヘッド(Virtual DOM is pure overhead) +description: "'仮想DOMは速い'という神話を完全に終わりにしよう" author: Rich Harris authorURL: https://bsky.app/profile/rich-harris.dev --- -If you've used JavaScript frameworks in the last few years, you've probably heard the phrase 'the virtual DOM is fast', often said to mean that it's faster than the _real_ DOM. It's a surprisingly resilient meme — for example people have asked how Svelte can be fast when it doesn't use a virtual DOM. +ここ数年でJavaScriptフレームワークを使ったことがある人なら、'仮想DOMは速い' というフレーズを聞いたことがあるでしょう、これはしばしば、実際のDOMよりも速い、という意味で言われることがあります。これは驚くほどしぶといミームです — 例えば、どうやってSvelteは仮想DOMを使わずに高速にできるのかを尋ねられることがありました。 -It's time to take a closer look. +では、じっくり見ていきましょう。 -## What is the virtual DOM? +## 仮想DOMとは? -In many frameworks, you build an app by creating `render()` functions, like this simple [React](https://reactjs.org/) component: +多くのフレームワークで、`render()`関数を作ってアプリを構築します。例えばシンプルな [React](https://reactjs.org/) コンポーネントでは: -```ts +```js // @noErrors function HelloMessage(props) { - return
Hello {props.name}
; + return ( +
+ Hello {props.name} +
+ ); } ``` -You can do the same thing without JSX... +JSXを使わずに同じことをするなら… ```js // @noErrors @@ -29,20 +33,21 @@ function HelloMessage(props) { } ``` -...but the result is the same — an object representing how the page should now look. That object is the virtual DOM. Every time your app's state updates (for example when the `name` prop changes), you create a new one. The framework's job is to _reconcile_ the new one against the old one, to figure out what changes are necessary and apply them to the real DOM. +…しかし、結果は同じで — ページがどのように見えるかを表現するオブジェクトになります。このオブジェクトは仮想DOMです。アプリのstateが更新されるたびに(例えば `name` prop が変わったとき)、これが新たに作成されます。フレームワークの仕事は、新しいオブジェクトと古いオブジェクトを _調整_ し、どのような変更が必要か把握して、実際のDOMにそれを適用することです。 -## How did the meme start? +## このミームはどう始まった? -Misunderstood claims about virtual DOM performance date back to the launch of React. In [Rethinking Best Practices](https://www.youtube.com/watch?v=x7cQ3mrcKaY), a seminal 2013 talk by former React core team member Pete Hunt, we learned the following: +仮想DOMのパフォーマンスに関する誤解された主張は、Reactの立ち上げまで遡ります。元ReactコアチームメンバーのPete Hunt氏による2013年の発展的な講演 [Rethinking Best Practices](https://www.youtube.com/watch?v=x7cQ3mrcKaY) で、私たちは次のことを学びました。 -> This is actually extremely fast, primarily because most DOM operations tend to be slow. There's been a lot of performance work on the DOM, but most DOM operations tend to drop frames. +> これは実際には非常に高速で、主な理由は、ほとんどのDOM操作は遅くなる傾向があるからです。DOMには多くのパフォーマンス作業がありますが、ほとんどのDOM操作はフレームをドロップする傾向があります。 +> ※原文 : This is actually extremely fast, primarily because most DOM operations tend to be slow. There's been a lot of performance work on the DOM, but most DOM operations tend to drop frames.
Pete Hunt at JSConfEU 2013
Screenshot from Rethinking Best Practices at JSConfEU 2013
-But hang on a minute! The virtual DOM operations are _in addition to_ the eventual operations on the real DOM. The only way it could be faster is if we were comparing it to a less efficient framework (there were plenty to go around back in 2013!), or arguing against a straw man — that the alternative is to do something no-one actually does: +しかし、ちょっと待ってください! 仮想DOMの操作は、実際のDOMに対する最終的な操作に _加えて_ 行われます。これを高速だと主張するには、より非効率なフレームワークと比較するか(2013年にはたくさんありました)、もしくは、実際には誰もやらないような架空の代替案に対して反論するしかありません。。 ```js // @noErrors @@ -51,29 +56,30 @@ onEveryStateChange(() => { }); ``` -Pete clarifies soon after... +Peteはすぐ後に明確にしました… -> React is not magic. Just like you can drop into assembler with C and beat the C compiler, you can drop into raw DOM operations and DOM API calls and beat React if you wanted to. However, using C or Java or JavaScript is an order of magnitude performance improvement because you don't have to worry...about the specifics of the platform. With React you can build applications without even thinking about performance and the default state is fast. +> Reactは魔法ではありません。C言語でアセンブラを使用してCコンパイラに勝つことができるのと同様に、必要に応じて生のDOMとDOM APIを使えばReactに勝つことができます。しかし、C や Java、JavaScript を使うと、プラットフォームの詳細について心配する必要がなくなるため、パフォーマンスが桁違いに向上します。Reactを使うことで、パフォーマンスを気にすることなくアプリケーションを構築することができますし、デフォルトの state は高速です。 +> ※原文 : React is not magic. Just like you can drop into assembler with C and beat the C compiler, you can drop into raw DOM operations and DOM API calls and beat React if you wanted to. However, using C or Java or JavaScript is an order of magnitude performance improvement because you don't have to worry...about the specifics of the platform. With React you can build applications without even thinking about performance and the default state is fast. -...but that's not the part that stuck. +…しかし、それは行き詰まった部分ではありません。 -## So... is the virtual DOM _slow_? +## それで…仮想DOMは遅い? -Not exactly. It's more like 'the virtual DOM is usually fast enough', but with certain caveats. +その表現は正しくありません。'仮想DOMは大抵、十分に速い'というほうがより近いですが、いくつかの注意点があります。 -The original promise of React was that you could re-render your entire app on every single state change without worrying about performance. In practice, I don't think that's turned out to be accurate. If it was, there'd be no need for optimisations like `shouldComponentUpdate` (which is a way of telling React when it can safely skip a component). +Reactの当初の約束は、パフォーマンスを心配することなく、state が1つ変更されるたびにアプリ全体を再レンダリングできる、というものでした。実際には、それは正確ではないと思います。もしそうなら、`shouldComponentUpdate` (コンポーネントを安全にスキップできるときにReactに伝える方法) のような最適化は必要ないはずです。 -Even with `shouldComponentUpdate`, updating your entire app's virtual DOM in one go is a lot of work. A while back, the React team introduced something called React Fiber which allows the update to be broken into smaller chunks. This means (among other things) that updates don't block the main thread for long periods of time, though it doesn't reduce the total amount of work or the time an update takes. +`shouldComponentUpdate` を使ったとしても、アプリ全体の仮想DOMを一度に更新するのは大変な作業です。しばらく前に、ReactチームはReact Fiberと呼ばれるものを導入し、更新をより小さなチャンクに分割できるようになりました。これは (とりわけ) 更新によってメインスレッドが長時間ブロックされないことを意味しますが、総作業量や更新にかかる時間が減るわけではありません。 -## Where does the overhead come from? +## オーバーヘッドはどこから? -Most obviously, [diffing isn't free](https://twitter.com/pcwalton/status/1015694528857047040). You can't apply changes to the real DOM without first comparing the new virtual DOM with the previous snapshot. To take the earlier `HelloMessage` example, suppose the `name` prop changed from 'world' to 'everybody'. +ほぼ間違いなく、[差分検出のコストはゼロではありません](https://twitter.com/pcwalton/status/1015694528857047040)(原文 : diffing isn't free)。まず仮想DOMとその直前のスナップショットの比較をしないと、変更を実際のDOMに適用できません。先ほどの `HelloMessage` の例で言えば、`name` propが 'world' から 'everybody' に変わったとします。 -1. Both snapshots contain a single element. In both cases it's a `
`, which means we can keep the same DOM node -2. We enumerate all the attributes on the old `
` and the new one to see if any need to be changed, added or removed. In both cases we have a single attribute — a `className` with a value of `"greeting"` -3. Descending into the element, we see that the text has changed, so we'll need to update the real DOM +1. どちらのスナップショットにも単一の要素が含まれています。どちらの場合もそれは `
` であり、同じ DOM ノードを維持できることを意味します。 +2. 古い `
` と新しい `
` のすべての属性を列挙して、変更、追加、削除する必要があるか調べます。どちらも、値が `"greeting"` の `className` 属性だけがあります。 +3. 要素に降りていくと、テキストが変更されていることがわかるので、実際のDOMを更新する必要があります。 -Of these three steps, only the third has value in this case, since — as is the case in the vast majority of updates — the basic structure of the app is unchanged. It would be much more efficient if we could skip straight to step 3: +この3つのステップのうち、今回のケースでは3番目のステップだけが価値を持ちます、というのも — ほとんどの更新がそうであるように — アプリの基本構造は変わっていないからです。3番目のステップに直接進むことができれば、より効率的です: ```js // @noErrors @@ -82,11 +88,12 @@ if (changed.name) { } ``` -(This is almost exactly the update code that Svelte generates. Unlike traditional UI frameworks, Svelte is a compiler that knows at _build time_ how things could change in your app, rather than waiting to do the work at _run time_.) +(これはSvelteが生成する更新のコードとほぼ同じです。従来のUIフレームワークとは異なり、Svelteは、 _実行時_ にこの作業をするのを待つのではなく、どのように変更されるか _ビルド時_ にわかるコンパイラです) + -## It's not just the diffing though +## 差分検出だけではありません -The diffing algorithms used by React and other virtual DOM frameworks are fast. Arguably, the greater overhead is in the components themselves. You wouldn't write code like this... +Reactや他の仮想DOMフレームワークで使われている差分検出アルゴリズムは高速です。議論の余地はありますが、より大きなオーバーヘッドはコンポーネント自体にあります。こんなコードは普通書かないと思います… ```js // @noErrors @@ -97,7 +104,7 @@ function StrawManComponent(props) { } ``` -...because you'd be carelessly recalculating `value` on every update, regardless of whether `props.foo` had changed. But it's extremely common to do unnecessary computation and allocation in ways that seem much more benign: +…なぜなら、`props.foo` が変更されたかどうかに関わらず、更新のたびに不注意に `value` を再計算してしまうからです。しかし、もっと無害に見える方法で、不必要な計算やアロケーションが行われてしまうことは非常に一般的です: ```js // @noErrors @@ -120,16 +127,16 @@ function MoreRealisticComponent(props) { } ``` -Here, we're generating a new array of virtual `
  • ` elements — each with their own inline event handler — on every state change, regardless of whether `props.items` has changed. Unless you're unhealthily obsessed with performance, you're not going to optimise that. There's no point. It's plenty fast enough. But you know what would be even faster? _Not doing that._ +ここでは、`props.items` が変化したかどうかに関わらず、仮想的な `
  • ` 要素の新しい配列(それぞれがインラインのイベントハンドラを持つ)をそれぞれの状態が変化するたびに生成しています。よっぽどパフォーマンスにこだわっていない限り、これを最適化することはないでしょう。意味がありません。これで十分に速いのですから。しかし、さらに速い方法がわかりますか? _こうしないことです_ 。 - + -The danger of defaulting to doing unnecessary work, even if that work is trivial, is that your app will eventually succumb to 'death by a thousand cuts' with no clear bottleneck to aim at once it's time to optimise. +デフォルトで不必要な作業を行うことは危険で、たとえその作業が些細なものであっても、最適化の際に明確なボトルネックがないためにアプリがやがて 'じわじわと破滅に向かう'(原文 : death by a thousand cuts)ことに屈してしまいます。 -Svelte is explicitly designed to prevent you from ending up in that situation. +Svelteは、そのような状況に陥らないよう明示的に設計されています。 -## Why do frameworks use the virtual DOM then? +## では、なぜフレームワークは仮想DOMを使うのか? -It's important to understand that virtual DOM _isn't a feature_. It's a means to an end, the end being declarative, state-driven UI development. Virtual DOM is valuable because it allows you to build apps without thinking about state transitions, with performance that is _generally good enough_. That means less buggy code, and more time spent on creative tasks instead of tedious ones. +重要なのは、仮想DOMは _機能ではない_ ということです。それは目的を達成するための手段であり、その目的とは宣言的で状態駆動型のUI開発です。仮想DOMは、状態遷移を考えることなくアプリケーションを開発できるようにし、 _一般的には十分な_ パフォーマンスを得られるという点で価値があります。つまり、バグを減らし、退屈な作業ではなく創造的な作業に多くの時間を費やすことができるようになります。 -But it turns out that we can achieve a similar programming model without using virtual DOM — and that's where Svelte comes in. +しかし、仮想DOMを使用せずに同様のプログラミングモデルを実現できることがわかりました — つまりSvelteの登場です。 diff --git a/apps/svelte.dev/content/blog/2019-04-20-write-less-code.md b/apps/svelte.dev/content/blog/2019-04-20-write-less-code.md index edb8796d45..39caf1f3c7 100644 --- a/apps/svelte.dev/content/blog/2019-04-20-write-less-code.md +++ b/apps/svelte.dev/content/blog/2019-04-20-write-less-code.md @@ -1,21 +1,21 @@ --- -title: Write less code -description: The most important metric you're not paying attention to +title: コード量を減らす(Write less code) +description: 注意が払われていない最も重要な指標について author: Rich Harris authorURL: https://bsky.app/profile/rich-harris.dev --- -All code is buggy. It stands to reason, therefore, that the more code you have to write the buggier your apps will be. +全てのコードにはバグが存在する可能性があります(All code is buggy)。したがって、書かなければいけないコードが多ければ多いほど、アプリケーションがバグだらけになるのは理にかなっています。 -Writing more code also takes more time, leaving less time for other things like optimisation, nice-to-have features, or being outdoors instead of hunched over a laptop. +多くのコードを書くには多くの時間がかかるので、他のこと(例えば最適化や、良い機能を開発すること、またはPCの前に座らずに外出することなど)に充てられる時間は少なくなります。 -In fact it's widely acknowledged that [project development time](https://blog.codinghorror.com/diseconomies-of-scale-and-lines-of-code/) and [bug count](https://www.mayerdan.com/ruby/2012/11/11/bugs-per-line-of-code-ratio) grow _quadratically_, not linearly, with the size of a codebase. That tracks with our intuitions: a ten-line pull request will get a level of scrutiny rarely applied to a 100-line one. And once a given module becomes too big to fit on a single screen, the cognitive effort required to understand it increases significantly. We compensate by refactoring and adding comments — activities that almost always result in _more_ code. It's a vicious cycle. +実際、[プロジェクトの開発時間](https://blog.codinghorror.com/diseconomies-of-scale-and-lines-of-code/) と [バグ件数](https://www.mayerdan.com/ruby/2012/11/11/bugs-per-line-of-code-ratio) はコードベースのサイズに対して直線的ではなく _二次関数的_ に増加することが広く知られています。これは私たちの直感と一致しています : 10行のプルリクエストは、100行のプルリクエストだと有り得ないレベルで精査されるでしょう。また、モジュールが1つの画面に収まりきらないほど大きくなると、それを理解するために必要な認知的努力が著しく増大します。リファクタリングし、コメントを追加することでこの問題に対応しようとしますが、ほとんどの場合コードがもっと増加してしまいます。悪循環です。 -Yet while we obsess — rightly! — over performance numbers, bundle size and anything else we can measure, we rarely pay attention to the amount of code we're writing. +しかし、私たちはパフォーマンスの数値やバンドルサイズ、その他計測できるものはなんでも気にかける一方で、書いているコードの量に注意を払うことはほとんどありません。 -## Readability is important +## 重要なのは読みやすさ(Readability is important) -I'm certainly not claiming that we should use clever tricks to scrunch our code into the most compact form possible at the expense of readability. Nor am I claiming that reducing _lines_ of code is necessarily a worthwhile goal, since it encourages turning readable code like this... +巧妙なトリックを使って読みやすさを犠牲にしてでもできるだけコードをコンパクトにするべきだ、と主張しているわけではありません。また、コードの _行数_ を減らすことこそが価値のある目標であると主張しているわけでもありません、このような主張は、例えば次のような読みやすいコードを… ```js for (let i = 0; i <= 100; i += 1) { @@ -25,17 +25,17 @@ for (let i = 0; i <= 100; i += 1) { } ``` -...into something much harder to parse: +…次のように解析がより難しいものに変えるよう促してしまいます: ```js for (let i = 0; i <= 100; i += 1) if (i % 2 === 0) console.log(`${i} is even`); ``` -Instead, I'm claiming that we should favour languages and patterns that allow us to naturally write less code. +代わりに、自然とコードが少なくなるような言語とパターンを好むべきだと主張します。 -## Yes, I'm talking about Svelte +## はい、Svelteについて話しています -Reducing the amount of code you have to write is an explicit goal of Svelte. To illustrate, let's look at a very simple component implemented in React, Vue and Svelte. First, the Svelte version: +書かなければいけないコードの量を減らすことは、Svelteの明確な目標です。説明のために、React、Vue、Svelteでそれぞれ実装されたシンプルなコンポーネントを見てみましょう。まずはSvelteのバージョンです:
    -How would we build this in React? It would probably look something like this: +これをReactで構築するには? おそらく次のようになるでしょう: ```js // @noErrors @@ -76,7 +76,7 @@ export default () => { }; ``` -Here's an equivalent component in Vue: +Vueで同等のことをやると次のようになります: ```svelte