eddev 0.2.28 → 0.2.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/build/get-webpack-config.js +1 -0
  2. package/gravityforms/useGravityForm.js +13 -3
  3. package/package.json +6 -5
  4. package/serverless-template/tsconfig.json +1 -0
  5. package/style/createStitches.js +10 -3
  6. package/docs_old/README.md +0 -33
  7. package/docs_old/babel.config.js +0 -3
  8. package/docs_old/blog/2019-05-28-first-blog-post.md +0 -12
  9. package/docs_old/blog/2019-05-29-long-blog-post.md +0 -44
  10. package/docs_old/blog/2021-08-01-mdx-blog-post.mdx +0 -20
  11. package/docs_old/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  12. package/docs_old/blog/2021-08-26-welcome/index.md +0 -25
  13. package/docs_old/blog/authors.yml +0 -17
  14. package/docs_old/docs/graphql/1.graphql-overview.md +0 -62
  15. package/docs_old/docs/graphql/2.query-hooks.md +0 -238
  16. package/docs_old/docs/graphql/3.extending-wpgraphql.md +0 -3
  17. package/docs_old/docs/graphql/_category_.json +0 -4
  18. package/docs_old/docs/graphql/img/graphql-ide.png +0 -0
  19. package/docs_old/docs/graphql/img/infinite-example.gif +0 -0
  20. package/docs_old/docs/graphql/img/mutation-example.gif +0 -0
  21. package/docs_old/docs/gutenberg/1.overview.md +0 -25
  22. package/docs_old/docs/gutenberg/2.block-definition.md +0 -37
  23. package/docs_old/docs/gutenberg/3.block-acf.md +0 -13
  24. package/docs_old/docs/gutenberg/4.block-graphql.md +0 -63
  25. package/docs_old/docs/gutenberg/5.inline-editing.md +0 -33
  26. package/docs_old/docs/gutenberg/6.nested-blocks.md +0 -80
  27. package/docs_old/docs/gutenberg/7.restricting-to-post-types.md +0 -38
  28. package/docs_old/docs/gutenberg/8.restricting-to-page-templates.md +0 -26
  29. package/docs_old/docs/gutenberg/9.dynamic-blocks.md +0 -21
  30. package/docs_old/docs/gutenberg/_category_.json +0 -4
  31. package/docs_old/docs/gutenberg/img/create-acf-fields-for-block.png +0 -0
  32. package/docs_old/docs/gutenberg/img/example-acf-single-project-tile.png +0 -0
  33. package/docs_old/docs/how-to/1.new-site.md +0 -36
  34. package/docs_old/docs/how-to/2.deployment.md +0 -31
  35. package/docs_old/docs/how-to/3.menus.md +0 -72
  36. package/docs_old/docs/how-to/4.options-pages.md +0 -41
  37. package/docs_old/docs/how-to/5.bundle-size.md +0 -177
  38. package/docs_old/docs/how-to/6.favicons.md +0 -82
  39. package/docs_old/docs/how-to/_category_.json +0 -4
  40. package/docs_old/docs/how-to/img/bundle-analysis-after.png +0 -0
  41. package/docs_old/docs/how-to/img/bundle-analysis-before.png +0 -0
  42. package/docs_old/docs/how-to/img/bundle-webpack-after.png +0 -0
  43. package/docs_old/docs/how-to/img/bundle-webpack-before.png +0 -0
  44. package/docs_old/docs/how-to/img/favicon-codebase.png +0 -0
  45. package/docs_old/docs/how-to/img/favicon-figma-export.png +0 -0
  46. package/docs_old/docs/how-to/img/favicon-figma.png +0 -0
  47. package/docs_old/docs/intro.md +0 -7
  48. package/docs_old/docs/known-issues.md +0 -8
  49. package/docs_old/docs/serverless/1.overview.md +0 -1
  50. package/docs_old/docs/serverless/2.config.md +0 -1
  51. package/docs_old/docs/serverless/3.wordpress-vercel.md +0 -8
  52. package/docs_old/docs/serverless/4.apis.md +0 -1
  53. package/docs_old/docs/serverless/5.rpc.md +0 -1
  54. package/docs_old/docs/serverless/_category_.json +0 -4
  55. package/docs_old/docs/stack/1-WordPress.md +0 -18
  56. package/docs_old/docs/stack/2-Flywheel.md +0 -15
  57. package/docs_old/docs/stack/3-React.md +0 -12
  58. package/docs_old/docs/stack/4-TypeScript.md +0 -13
  59. package/docs_old/docs/stack/5-WPGraphQL.md +0 -21
  60. package/docs_old/docs/stack/6-eddev.md +0 -9
  61. package/docs_old/docs/stack/_category_.json +0 -4
  62. package/docs_old/docs/tooling/1.scripts.md +0 -25
  63. package/docs_old/docs/tooling/2.aliases.md +0 -13
  64. package/docs_old/docs/tooling/3.defines.md +0 -13
  65. package/docs_old/docs/tooling/4.config-file.md +0 -14
  66. package/docs_old/docs/tooling/_category_.json +0 -4
  67. package/docs_old/docs/views/1.overview.md +0 -31
  68. package/docs_old/docs/views/2.queries.md +0 -18
  69. package/docs_old/docs/views/3.content-blocks.md +0 -36
  70. package/docs_old/docs/views/4.app-view.md +0 -35
  71. package/docs_old/docs/views/5.page-templates.md +0 -20
  72. package/docs_old/docs/views/_category_.json +0 -4
  73. package/docs_old/docusaurus.config.js +0 -119
  74. package/docs_old/package.json +0 -40
  75. package/docs_old/sidebars.js +0 -26
  76. package/docs_old/src/components/HomepageFeatures.js +0 -64
  77. package/docs_old/src/components/HomepageFeatures.module.css +0 -11
  78. package/docs_old/src/css/custom.css +0 -28
  79. package/docs_old/src/pages/index.js +0 -36
  80. package/docs_old/src/pages/index.module.css +0 -23
  81. package/docs_old/src/pages/markdown-page.md +0 -7
  82. package/docs_old/static/.nojekyll +0 -0
  83. package/docs_old/static/img/docusaurus.png +0 -0
  84. package/docs_old/static/img/favicon.ico +0 -0
  85. package/docs_old/static/img/logo-black.svg +0 -4
  86. package/docs_old/static/img/logo-white.svg +0 -4
  87. package/docs_old/static/img/tutorial/docsVersionDropdown.png +0 -0
  88. package/docs_old/static/img/tutorial/localeDropdown.png +0 -0
  89. package/docs_old/static/img/undraw_docusaurus_mountain.svg +0 -170
  90. package/docs_old/static/img/undraw_docusaurus_react.svg +0 -169
  91. package/docs_old/static/img/undraw_docusaurus_tree.svg +0 -1
  92. package/docs_old/yarn.lock +0 -8814
@@ -1,13 +0,0 @@
1
- # Block ACF Fields
2
-
3
- Once you've created a `.tsx` file for your block, it'll automatically be registered with WordPress, and is available to be targetted by ACF field groups.
4
-
5
- - Create a new ACF Field Group
6
- - Make sure the block title starts with `Block: ` — this is just convention
7
- - Add any fields you like.
8
-
9
- ![Adding an ACF Field Group for a Block](./img/create-acf-fields-for-block.png)
10
-
11
- :::tip
12
- We may add the ability to have [ACF Builder](https://github.com/StoutLogic/acf-builder) support for blocks at some point, however for now it's recommended that you use the ACF Interface to build fields for your blocks. ACF Builder is an advanced tool which requires that you have a deeper knowledge of ACF and all of it's configuration options, and may be harder to use for ACF newbies.
13
- :::
@@ -1,63 +0,0 @@
1
- # Block GraphQL Files
2
-
3
- ## Naming
4
-
5
- A block named `/blocks/sections/newsletter.tsx` can have a single GraphQL query file named `/blocks/sections/newsletter.graphql`.
6
-
7
- Due to a limitation with GraphQL Codegen, each `.graphql` file must contain one uniquely-named.
8
-
9
- ACF fields attached to the block can be queried using the naming convention `folderName_blockName`, where the folder name and block name are automatically converted from `dash-case` to `camelCase`.
10
-
11
- ## Execution
12
-
13
- Block queries are executed automatically by PHP code, so there is no need to call any functions to get the data, or handle any loading/error state. The result of the query is sent straight into the `props` of your block.
14
-
15
- ## Querying ACF Fields
16
-
17
- GraphQL schemas for your blocks ACF Fields are automatically generated by PHP.
18
-
19
- Consider this block type:
20
-
21
- ```tsx title="blocks/project/single-project-tile.tsx"
22
- /**
23
- * Title: Single Project Tile
24
- * Description: Displays a single project as a large tile.
25
- * Category: common
26
- * Icon: book-alt
27
- * Keywords: post
28
- * Types: page, post
29
- * Mode: preview
30
- * Supports multiple: true
31
- */
32
- import { defineBlock, EditableText, InnerBlocks } from "eddev/blocks"
33
-
34
- export default defineBlock("project/single-project-tile", (props) => {
35
- return <div>...</div>
36
- })
37
- ```
38
-
39
- With the following ACF field configuration:
40
-
41
- ![Example block](./img/example-acf-single-project-tile.png)
42
-
43
- The ACF fields will be available under `block.project_singleProjectTile`
44
-
45
- ```graphql title="blocks/project/single-project-tile.graphql"
46
- query SingleProjectTile {
47
- block {
48
- project_singleProjectTile {
49
- project {
50
- ... on Project {
51
- id
52
- title(format: RENDERED)
53
- projectFields {
54
- image {
55
- ...BasicImage
56
- }
57
- }
58
- }
59
- }
60
- }
61
- }
62
- }
63
- ```
@@ -1,33 +0,0 @@
1
- # Inline Editing
2
-
3
- It's trivial to add inline editing to your blocks. This is totally separate from ACF.
4
-
5
- ## `<EditableText />`
6
-
7
- The most common inline editing function will of course be the ability to edit text in your block. The `<EditableText>` component does just this! Keep in mind, this can only be used on blocks, or components which are used within a block.
8
-
9
- ```tsx
10
- <div>
11
- <EditableText as="h2" id="title" placeholder="Enter a title" />
12
- </div>
13
- ```
14
-
15
- When the above code runs in the WordPress editor, an author can click on that element and type into it directly.
16
-
17
- Note that you can have as many `<EditableText>` components as you want, however each `id` must be unique, since each value is stored as a key/value pair.
18
-
19
- The `as` prop is required, and can either be an element type (`p`, `h1`, `h2`, etc.) or a component.
20
-
21
- ## `useInlineEditableValue`
22
-
23
- The `useInlineEditableValue` hook is the foundation of all inline editing in our system — it works a lot like `useState`, except that the content is saved to the block when saving the page, and restored again when the page is loaded.
24
-
25
- Much like `EditableText`, the hook requires a unique `id` to identify the value.
26
-
27
- You can store any kind of data, including objects and arrays.
28
-
29
- ```tsx
30
- const [title, setTitle] = useInlineEditableValue('title');
31
-
32
- return <input type="text" value={title} onChange={e => setTitle(e.currentTarget.value)}>
33
- ```
@@ -1,80 +0,0 @@
1
- # Nested Blocks
2
-
3
- Nested blocks add a lot of power to Gutenberg — you can create blocks, which themselves contain more blocks.
4
-
5
- The `<InnerBlocks />` component acts as a container for child blocks.
6
-
7
- Note that you can only have ONE `InnerBlocks` per-block. This is a WordPress limitation.
8
-
9
- ## Block Tagging
10
-
11
- Most of the time, we want to restrict where blocks can be used. For example, we might have a set of 'root' blocks which the user can only be added to the root of the page. Then, we might want some 'inline' blocks which can be added to some of those root blocks. We may also have specialised blocks, like a 'Button Row', which can only accept 'Button' blocks.
12
-
13
- To do this, we've invented a 'tags' system for blocks, which is defined in the comments section of a block.
14
-
15
- ```tsx
16
- /*
17
- * ...
18
- * Tags: root
19
- * Child tags: inline
20
- */
21
- ```
22
-
23
- Use 'Tags' to define the tags on this block, as a comma separated list if defining multiple tags. The `'root'` tag is special, in that any block tagged with it can be added to the root of the page.
24
-
25
- If the block has `InnerBlocks`, you can use `Child tags` to indirectly specify the allowed block types which can be added to this block.
26
-
27
- ## Tagging core blocks
28
-
29
- You can also tag core blocks, which are blocks which are included by WordPress, using some PHP code.
30
-
31
- Note that you can tag core blocks multiple times with multiple tags.
32
-
33
- ```php title="backend/blocks.php"
34
- <?php
35
-
36
- ED()->tagCoreBlocks("wysiwyg", [
37
- "core/paragraph",
38
- "core/list",
39
- "core/heading",
40
- ]);
41
-
42
- ?>
43
- ```
44
-
45
- ## Putting it all together
46
-
47
- For example, if you have a 'Section' block which accepts some WYSIWYG blocks like headings and paragraphs as well as a 'Button Row' block, and only want to allow 'Button' blocks to be added to the 'Button Row', you might have something like this:
48
-
49
- ```tsx title="blocks/layout/section.tsx"
50
- /*
51
- * ...
52
- * Tags: root
53
- * Child tags: inline, wysiwyg
54
- */
55
- ```
56
-
57
- ```tsx title="blocks/buttons/button-row.tsx"
58
- /*
59
- * ...
60
- * Tags: inline
61
- * Child tags: buttons
62
- */
63
- ```
64
-
65
- ```tsx title="blocks/buttons/button.tsx"
66
- /*
67
- * ...
68
- * Tags: buttons
69
- */
70
- ```
71
-
72
- ```php title="backend/blocks.php"
73
-
74
- ED()->tagCoreBlocks("wysiwyg", [
75
- "core/paragraph",
76
- "core/list",
77
- "core/heading",
78
- ]);
79
-
80
- ```
@@ -1,38 +0,0 @@
1
- # Restricting to Post Types
2
-
3
- You can restrict an individual block type to only be used in certain post types.
4
-
5
- To do this, just update your block's `Types` property. You can have multiple types, separated by commas.
6
-
7
- ```tsx
8
- /*
9
- * ...
10
- * Types: page, post
11
- * ...
12
- */
13
- ```
14
-
15
- ### Template Locking
16
-
17
- Taking this a step further, you can also specify required root blocks for a post type.
18
-
19
- For example, you might want to specify that when creating a new blog post, that only 'Blog Post Header' and 'Blog Post Content' blocks are added to root, and are automatically added when creating a new post, and also cannot be removed.
20
-
21
- This needs to be done in PHP:
22
-
23
- ```php title="backend/blocks.php"
24
- <?php
25
-
26
- ED()->templateLock([
27
- 'type' => 'post',
28
- 'content' => [
29
- ['acf/blog-post-header'],
30
- ['acf/blog-post-content'],
31
- ]
32
- ]);
33
-
34
- ```
35
-
36
- :::warning
37
- Note that you need to use the internal ACF block name when working with template locks. For example, `blog/post-header` becomes `acf/blog-post-header`.
38
- :::
@@ -1,26 +0,0 @@
1
- # Restricting to Page Templates
2
-
3
- You can restrict an individual block type to only be used in certain page templates
4
-
5
- To do this, just update your block's `Templates` property. You can have multiple templates, separated by commas.
6
-
7
- ```tsx
8
- /*
9
- * ...
10
- * Types: page, post
11
- * Templates: templates/my-cool-template
12
- * ...
13
- */
14
- ```
15
-
16
- :::tip
17
- Be sure to set `Types: page`, otherwise the block wont be available in the page template.
18
- :::
19
-
20
- :::warning
21
- Note that in above example, the block will be available on all `post`s, and all `page`s which have the template `views/templates/my-cool-template.tsx`.
22
- :::
23
-
24
- ### Template Locking
25
-
26
- Unfortunately this isn't possible at the moment... mostly due to Gutenberg being a bit crap.
@@ -1,21 +0,0 @@
1
- # Dynamic Blocks
2
-
3
- A "dynamic" block is a block that loads asynchronously, only when it's used for the first time. This is useful when a block has a large dependency (think, THREE.js or Swiper). This can drastically reduce the size of your bundle, while also improving the loading time of your site.
4
-
5
- The downside is that the block won't load until it's first use, which means that it'll be hidden for a moment while it loads. Because of this, it's recommended that you:
6
-
7
- - Perhaps don't use this feature if your block is likely to be used above-the-fold (maybe a good candidate for dynamic components or dynamic imports)
8
- - Do a fade in animation when the block is first mounted, so that it's not a jarring experience.
9
-
10
- It's super easy to enable this feature — just add `Dynamic: true` to your block header comment.
11
-
12
- ```tsx title="/blocks/layouts/section.tsx"
13
- /**
14
- * Title: TITLE
15
- * Description: DESCRIPTION
16
- * ...etc
17
- * Dynamic: true
18
- */
19
- ```
20
-
21
- You can read more about dynamic _components_, and other ways to reduce your bundle size here — [Bundle Size Tips &rarr;](../how-to/bundle-size)
@@ -1,4 +0,0 @@
1
- {
2
- "label": "🧱 Gutenberg Blocks",
3
- "position": 4
4
- }
@@ -1,36 +0,0 @@
1
- # Creating a new site
2
-
3
- ### Initial Setup
4
-
5
- 1. [Create a new repo on Github](https://github.com/new)
6
- 1. Set `Owner` to `ed-digital`, and name your repo like `some-client-name`.
7
- 2. Set `Repository Template` to `ed-digital/eddev-starter-theme`
8
- 3. Hit `Create repository`
9
- 2. Create a new site in Local, on your computer.
10
- 1. Use the default settings
11
- 2. Be sure to use `ed_admin` as the username, and create a secure password using 1pass or similar, and the email address should be `web@ed.com.au`
12
- 3. Save the username and password to 1pass.
13
- 3. Install the following plugins:
14
- 1. Advanced Custom Fields Pro ([download](https://www.advancedcustomfields.com/my-account/view-licenses/)
15
- 2. Add `b3JkZXJfaWQ9NDA3NDN8dHlwZT1kZXZlbG9wZXJ8ZGF0ZT0yMDE0LTA5LTI3IDA4OjUwOjIx` as the key for ACF Pro under 'Custom Fields > Updates'
16
- 3. Yoast SEO — install from plugins dashboard
17
- 4. Gutenberg — install from plugins dashboard
18
- 5. Nested Pages — install from plugins dashboard
19
- 6. Admin Menu Editor — install from plugins dashboard (use this to hide unused sidebar items, and tidy up the menu for clients.)
20
- 4. Under Settings -> General, remove 'Just another WordPress Site' and set Timezone to Sydney.
21
- 6. Make sure that all the installed plugins have been activated.
22
- 7. Clone your newly created theme to `wp-content/themes/`, making sure that the repo name and the theme folder name are identical.
23
- 8. Run the following commands inside the theme folder
24
- 1. `composer update`
25
- 2. `yarn`
26
- 3. `yarn add --dev eddev`
27
- 4. `yarn setup`
28
- 9. Activate the theme under Appearance > Themes
29
- 10. Run `yarn dev`
30
-
31
- ### Initial Flywheel Setup
32
-
33
- 1. [Create a new site on Flywheel](https://app.getflywheel.com/new-site)
34
- 1. Select 'My Organisation'
35
- 2. The username and password are irrelevant, as they'll soon be overridden with your locally created details.
36
- 2. Once complete, restart Local, and do an initial push to the new site, deploying to 'Production' with 'Include Database' selected.
@@ -1,31 +0,0 @@
1
- # Deployment
2
-
3
- There are some prerequisites for setting up deployment.
4
-
5
- 1. You've got an SSH key set up on your computer, which has been added to both Github and Flywheel. You only need to do this once for your computer.
6
- 2. You've set up the site on Flywheel already, and completed an initial push using Local Sync.
7
-
8
- Assuming the above prerequisites are met, setting up deployment is easy!
9
-
10
- 1. Grab the Flywheel SSH user for your site.
11
- 1. On the [Flywheel Dashboard](https://app.getflywheel.com/sites), locate the relevant site.
12
- 2. Click the 'Advanced' tab.
13
- 3. Copy the user component from the 'Connect via SSH' section.
14
- (For example, if the connection string is `ssh team+ed-digital+the-yards@ssh.getflywheel.com`), the value is `team+ed-digital+the-yards`.
15
- 2. Grab your private key.
16
- 1. Assuming you're using your default private key, and that it's in the correct format already, you can just run `cat ~/.ssh/id_rsa | pbcopy` in your terminal to copy this directly to your clipboard.
17
- 3. Paste the secrets into the Github repo's 'Secrets' panel.
18
- 1. Open the repo on Github, and click Settings -> Secrets.
19
- 2. Add a new secret called `SSH_USER` and paste in the value from step 1. Save it!
20
- 3. Add a new secret called `PRIVATE_KEY` and paste in the value from step 2. Save it!
21
- 4. Finally, rename `.github/workflows/main.yaml.disabled` to `.github/workflows/main.yaml` and commit/push the results.
22
- ```
23
- mv .github/workflows/main.yaml.disabled .github/workflows/main.yaml
24
- git commit -am "Enable Github Action deployment"
25
- git push
26
- ```
27
- 5. Monitor the 'Actions' tab on your Github repo page to ensure that the first deployment succeeded.
28
-
29
- :::tip warning
30
- Your first deploy might fail to run at the 'Install Dependencies' step. Try running 'Re-run all jobs'.
31
- :::
@@ -1,72 +0,0 @@
1
- # Menus
2
-
3
- For simplicities sake, all menus are pre-loaded in the starter theme's `views/_app.graphql`. It looks something like this:
4
-
5
- ```graphql title="views/_app.graphql"
6
- query CommonData {
7
- menus {
8
- nodes {
9
- menuItems {
10
- nodes {
11
- ...MenuItemFields
12
- }
13
- }
14
- locations
15
- slug
16
- name
17
- }
18
- }
19
- }
20
-
21
- fragment MenuItemFields on MenuItem {
22
- label
23
- title
24
- target
25
- url
26
- cssClasses
27
- childItems {
28
- nodes {
29
- label
30
- title
31
- target
32
- url
33
- cssClasses
34
- }
35
- }
36
- }
37
- ```
38
-
39
- The fragment is used there so that it's easy to grab TypeScript types for the menu data structure.
40
-
41
- There's also a `backend/menus.php` file, which has a call to `register_nav_menus` function call, which sets up 'menu locations'. If you need more than just one menu, you can add them there.
42
-
43
- ```php
44
- register_nav_menus([
45
- 'main' => 'Main Menu',
46
- 'footer' => 'Footer Menu'
47
- ]);
48
- ```
49
-
50
- The starter theme also comes with a `components/atoms/Menu.tsx` component. It's included as a component which you can tailor to your needs.
51
-
52
- To use the menu component, you'll need to specify the menu location which you defined in PHP. Assuming you've got `yarn dev` running, the menu locations will auto-complete with TypeScript.
53
-
54
- ```tsx
55
- <Menu location="Main">
56
- ```
57
-
58
- It's recommended that if you need to stylise or customise the Menu, that you kinda keep that file nice and generic, and create a new component which uses the `Menu` component as a base. (Or alternatively, you can always copy/paste the `Menu` code into your new component.)
59
-
60
- ```tsx title="components/atoms/MyCoolMenu.tsx
61
- import { Menu } from "@components/atoms/Menus"
62
-
63
- export const MyCoolMenu = styled(Menu, {
64
- display: "flex",
65
- li: {
66
- marginLeft: "20px",
67
- a: {
68
- fontFamily: '"Comic Sans"',
69
- },
70
- },
71
- })
72
- ```
@@ -1,41 +0,0 @@
1
- # Options Pages
2
-
3
- You can create an 'Options Page' on the WordPress sidebar to create a space for global ACF fields.
4
-
5
- Creating and consuming an options page can be completed in a few steps:
6
-
7
- 1. Create a new Options Page — check out `backend/options.php` for some example code, noting that `show_in_graphql` must be set to `true`.
8
- 2. Create a new ACF field group, with the fields you need.
9
- 1. Set the Location Rule to `Options Page` `is equal to` `<your new options page>`.
10
- 2. Make sure `Show in GraphQL` is checked.
11
- 3. Set `GraphQL Field Name` to something short and sweet, using pascalCase, eg `myOptions`.
12
- 3. Check the GraphiQL IDE, and look for a root-level field with a similar name to the `menu_slug` defined in your PHP, code, eg. `themeGeneralSettings`. It should have a child field with you `GraphQL Field Name`, which contains your settings!
13
-
14
- The PHP code should look something like this:
15
-
16
- ```php
17
- acf_add_options_page([
18
- 'page_title' => 'Theme Settings',
19
- 'menu_title' => 'Theme Settings',
20
- 'menu_slug' => 'theme-general-settings',
21
- 'capability' => 'edit_posts',
22
- 'redirect' => false,
23
- 'show_in_graphql' => true
24
- ]);
25
- ```
26
-
27
- Assuming that all worked, you can then query these fields in an `.graphql` file. If it needs to be globally accessible, you can add it to the `_app.graphql` file, and access it using the `useAppData` hook. It'll even be typed with TypeScript.
28
-
29
- ```graphql title="views/_app.graphql"
30
- query AppData {
31
- themeGeneralSettings {
32
- myOptions {
33
- footerText
34
- }
35
- }
36
- }
37
- ```
38
-
39
- ```tsx
40
- const footerText = useAppData((data) => data?.themeGeneralSettings?.myOptions?.footerText)
41
- ```
@@ -1,177 +0,0 @@
1
- # Bundle Size Tips
2
-
3
- ## Inspecting Bundle Size
4
-
5
- You can quite easily see the production size of your app by running:
6
-
7
- ```bash
8
- yarn build
9
- ```
10
-
11
- ![Webpack Result](./img/bundle-webpack-before.png)
12
-
13
- Above, we can see that the bundle size is 1.34mb, which is quite large. The note from Webpack says that we should aim for 244kb, which is really quite small. When we eventually move to serverless (via Vercel) for production frontends, we'll certainly aim for this smaller size. For now, with WordPress hosting, 600-700kb is fine. React itself takes up a bit of space on it's own.
14
-
15
- Let's dig deeper into why the bundle is so large.
16
-
17
- Our compile system includes the official [Webpack Bundle Analyzer](https://www.npmjs.com/package/webpack-bundle-analyzer) plugin. You can get a detailed analysis of the bundle size using the following:
18
-
19
- ```bash
20
- yarn build
21
- open dist/frontend/bundle-report.html
22
- ```
23
-
24
- Your browser will launch the bundle report, which will look something like this.
25
-
26
- ![Bundle Size Output](./img/bundle-analysis-before.png)
27
-
28
- You can see in the example above, that `hls.js` and `moment` + `moment-timezone` are taking up _a lot_ of the bundle size.
29
-
30
- What can we do about this?
31
-
32
- ## Choosing better libraries
33
-
34
- In the example above, `moment` is taking up SO much space, for something that is so simple. There are much simpler and smaller libraries that can be used instead.
35
-
36
- - If all you want is date formatting, check out `date-fns` — which provides a nifty date formatting function. The library is tree-shakable, meaning only the functions from that library you actually use in your code will be included in the bundle. [date-fns &rarr;](https://date-fns.org/)
37
- - If you need something a little more powerful, or if you need something related to timezones, check out `luxon`, which is made by the same team that created `moment`. It's a much lighter alternative, because even though it supports timezones, it uses native browser APIs, instead of bundling info on every timezone/locale. [Luxon &rarr;](https://moment.github.io/luxon/index.html#/?id=luxon)
38
- - (ps. Luxon doesn't come with TypeScript types, but you can install them using `yarn add --dev @types/luxon`)
39
-
40
- It's always worth reconsidering the libraries we choose, looking for the most modern libraries for certain functions.
41
-
42
- ## Dynamic imports
43
-
44
- Next up is `hls.js`. It's a library that provides a simple way to load and play HLS streams. It's not huge, but we probably don't need to include it in the main bundle.
45
-
46
- Say we have the following code:
47
-
48
- ```tsx
49
- import Hls from "hls.js"
50
-
51
- // ...
52
-
53
- useEffect(() => {
54
- const video = ref.current!
55
- if (src) {
56
- if (video.canPlayType("application/vnd.apple.mpegurl")) {
57
- // HLS is already supported natively by this browser
58
- video.src = props.url
59
- } else {
60
- // HLS is not supported by the browser. Use Hls.js instead!
61
- const hls = new Hls()
62
- hls.loadSource(props.url!)
63
- hls.attachMedia(video)
64
- return () => {
65
- hls.destroy()
66
- }
67
- }
68
- }
69
- }, [src])
70
- ```
71
-
72
- We can quite easily refactor this code to use dynamic imports, which will automatically split that library into it's own file, which will be imported separately only if/when it's needed. If we still need TypeScript types for the module, we can also use `import type` syntax, which will only import the types for TypeScript's sake, and not the module itself.
73
-
74
- ```tsx
75
- import type Hls from "hls.js"
76
-
77
- // ...
78
-
79
- useEffect(() => {
80
- const video = ref.current!
81
- if (props.url) {
82
- if (video.canPlayType("application/vnd.apple.mpegurl")) {
83
- // HLS is already supported natively by this browser
84
- video.src = props.url
85
- } else {
86
- // HLS is not supported by the browser. Use Hls.js instead!
87
- // Declare a reference to the object, so we can can still destroy it when the component transitions out
88
- let hls: Hls
89
- import("hls.js").then(({ default: Hls }) => {
90
- // hls.js has been successfully dynamically imported.
91
- // Assign to the `hls` variable, so that it can be destroyed properly
92
- hls = new Hls()
93
- hls.loadSource(props.url!)
94
- hls.attachMedia(video)
95
- })
96
- return () => {
97
- // Destroy the hls video, as long as it was created in the first place
98
- if (hls) {
99
- hls.destroy()
100
- }
101
- }
102
- }
103
- }
104
- }, [props.url])
105
- ```
106
-
107
- ## Dynamicly imported components
108
-
109
- Similar to Next's `next/dynamic` [(link)](https://nextjs.org/docs/advanced-features/dynamic-import), we have our own `eddev/dynamic` function. This allows you dynamically load components from the `components/*` directory using dynamic imports.
110
-
111
- ```tsx title="blocks/homepage/some-block.tsx"
112
- import { dynamic } from "eddev/dynamic"
113
-
114
- const MyDynamicComponent = dynamic(() => import("@components/something/my-dynamic-component"))
115
-
116
- export default defineBlock("homepage/some-block", () => {
117
- return (
118
- <div>
119
- <p>I appear instantly</p>
120
- <MyDynamicComponent fallback={<div>Loading...</div>} />
121
- </div>
122
- )
123
- })
124
- ```
125
-
126
- All the same props from `MyDynamicComponent` are available, and the fallback (which is optional) is added as a prop by the `dynamic` function. It'll show the fallback while the component is loading.
127
-
128
- When using this feature, you may notice a flash while the component is being loaded, since your page will actually render without the dynamic component first. This means that it may not always be suitable if the component is typically "above the fold". You may want to consider showing a placeholder div, and/or fading in the component using an animation once it's loaded.
129
-
130
- It's also important to note that the dynamic function expects (by default), a `default` export. Normally, we prefer to export named components, but in this case, `default` is good.
131
-
132
- ```tsx title="components/something/my-dynamic-component.tsx"
133
- // BAD: export function MyDynamicComponent() {}
134
- // GOOD:
135
- export default function MyDynamicComponent() {
136
- return <div>I'm a dynamic component!</div>
137
- }
138
- ```
139
-
140
- Internally, we use `@loadable/components` — you can see other options for `dynamic` via their [docs](https://loadable-components.com/). Next also uses this library!
141
-
142
- ## Dynamically imported blocks
143
-
144
- The `eddev/dynamic` function requires a tiny bit of boilerplate to get going. If you'd like to make a whole _block_ load dynamically, it's even easier. Note though that you wont be able to show a loading fallback.
145
-
146
- Just add `Dynamic: true` to your block header comment — the compiler will spot this, and automatically turn it into a dynamic component. That's it!
147
-
148
- ```tsx title="blocks/homepage/some-block.tsx"
149
- /**
150
- * Title: Some Block
151
- * Description: A block that does something cool
152
- * Category: common
153
- * Icon: book-alt
154
- * Keywords: post
155
- * Templates: default
156
- * Types: page
157
- * Mode: preview
158
- * Supports multiple: true
159
- * Tags: root
160
- * Child Tags: none
161
- * Dynamic: true
162
- */
163
- ```
164
-
165
- ^ The last line is the important part. You can read more about dynamic blocks [here](../gutenberg/dynamic-blocks).
166
-
167
- ## Validating the changes
168
-
169
- In the top sections above, we swapped from `moment` to `luxon`, and we also made `hls.js` a dynamic import.
170
-
171
- After running `yarn build` again, and checking out the visualizer, we can see that these two small changes have reduced our main bundle size by **HALF**.
172
-
173
- ![Webpack Result](./img/bundle-webpack-after.png)
174
-
175
- ![Bundle Size Output](./img/bundle-analysis-after.png)
176
-
177
- We could take this even further if we wanted, by making any blocks which use Swiper dynamic blocks, as discussed above.