diff --git a/packages/toolkit/README.md b/packages/toolkit/README.md index 70aa3b39..a14e4545 100644 --- a/packages/toolkit/README.md +++ b/packages/toolkit/README.md @@ -2,156 +2,599 @@ A collection of bundled scripts for 10up development. -## Install -``` +1. [Introduction](#introduction) +2. [Authoring Projects](#projects) +3. [Linting](#linting) +4. [Authoring Libraries](#libraries) +5. [Customizations](#customizations) +6. [CLI Options](#cli) +8. [TypeScript Support](#typescript) + +## Introduction + +10up-toolkit is 10up's official asset bundling tool based on Webpack 5. It comes with support for many things commonly +used across 10up's projects such as: +- JavaScript transpilation through babel +- core-js@3 automatic polyfill injection (project mode) +- PostCSS, SASS and CSS Modules +- ESLint and prettier +- Jest + +With 10up-toolkit, engineers can quickly and easily bundle assets for both production and development without having +to worry about config files. 10up-toolkit is also easy to extend to project's specifics needs. + +`10up-toolkit` is inspired in tools like `react-scripts`, `kcd-scripts` and `wp-scripts`. + +### Installation + +To install 10up-toolkit simply run + +```bash{showPrompt} npm install --save-dev 10up-toolkit ``` -## Scripts +### Setting it up + +In order to get `10up-toolkit` up and running simply define the `source` and `main` properties in your `package.json` file. +You can also specify a `style` property to tell `10up-toolkit` where to output your compiled css. +```json +{ + "name": "your-package-name", + "version": "1.0.0", + "main": "./dist/index.js", + "source": "./src/index.js", + "style": "./dist/index.css", + "scripts": { + "build": "10up-toolkit build", + "dev": "10up-toolkit build --watch" + } +} ``` -10up-toolkit build + +Then, the following code: +```javascript +// src/index.js +import './styles.css'; + +export default () => { /* my awesome js code */}; ``` -Builds CSS and JavaScript files. This uses the 10up configuration for Webpack. Check out the entry points below to see what is builds. +will generate a `index.js` and a `index.css` file in the `dist` folder after running `npm run build`. + +10up-toolkit can run in two different modes: package mode and project mode: +- **Project Mode**: Allows bundling multiple entry points and automatically includes core-js polyfills. +- **Package Mode**: Does not include core-js polyfills automatically, assumes one entry point and doesn't include dependencies in the bundle. + +By default it will run in package mode (like in the example above) and it works +well when you're building a package for distribution. + +## Authoring Projects + +When running in **project mode** 10up-toolkit will automatically inject core-js polyfills and also allow for multiple entry points. + +10up's [wp-scaffold](https://github.com/10up/wp-scaffold/blob/trunk/themes/10up-theme/package.json) is a good example of 10up-toolkit being used in project mode. + +Here's how a `package.json` would look like for using 10up-toolkit this way: +```json +{ + "name": "tenup-theme", + "version": "1.0.0", + "scripts": { + "start": "10up-toolkit build --watch", + "build": "10up-toolkit build", + "format-js": "10up-toolkit format-js", + "lint-js": "10up-toolkit lint-js", + "lint-style": "10up-toolkit lint-style", + "test": "10up-toolkit test-unit-jest", + }, + "devDependencies": { + "10up-toolkit": "^1.0.0" + }, + "dependencies": { + "normalize.css": "^8.0.1", + "prop-types": "^15.7.2" + }, + "10up-toolkit": { + "devURL": "https://my-project.test", + "entry": { + "admin": "./assets/js/admin/admin.js", + "blocks": "./includes/blocks/blocks.js", + "frontend": "./assets/js/frontend/frontend.js", + "shared": "./assets/js/shared/shared.js", + "styleguide": "./assets/js/styleguide/styleguide.js", + "admin-style": "./assets/css/admin/admin-style.css", + "editor-style": "./assets/css/frontend/editor-style.css", + "shared-style": "./assets/css/shared/shared-style.css", + "style": "./assets/css/frontend/style.css", + "styleguide-style": "./assets/css/styleguide/styleguide.css", + "core-block-overrides": "./includes/core-block-overrides.js", + "example-block": "./includes/blocks/example-block/index.js" + } + } +} ``` -10up-toolkit start + +Note the `10up-toolkit` object in `package.json`. It exposes a few options to configure 10up-toolkit behavior. +The most important is the `entry` option. It's an object where you can specify all of the entry points you need in your project. You can specify both JavaScript/TypeScript files or CSS/PostCSS/SASS files. + +When you run `10up-toolkit build` with this configuration, 10up-toolkit will generate compiled assets for every entry point in the dist folder. + +By default the compiled assets will be generated on the following diretories: +- `dist/css` - for all css files +- `dist/js` - for all js files. +- `dist/blocks` - for all WordPress Gutenberg blocks. +- `dist/[images,fonts,svg]` - all assets under `assets/images`, `asset/fonts` and `assets/svg` are copied, even those not referenced in code (this behavior is specific to building in project mode). + +See the [Customizing build paths](#customize-build-paths) section for changing the structure of the dist folder. + +### BrowserSync + +10up-toolkit ships with [BrowserSync](https://browsersync.io/) and can be enabled by simply adding a devURL property. + +```json + "10up-toolkit": { + "devURL": "https://my-project.test", + "entry": { + //... + } + } ``` -Builds CSS and JavaScript and watches files for changes. +In the example above, running `10up-toolkit start` or `10up-toolkit build --watch` will start 10up-toolkit in watch mode and start a browser sync session, proxying the *https://my-project.test* url. + +### Customizing build paths + +To change where assets are generated in the `dist` folder, you can create a `filenames.config.js` at the root of your project. +```javascript +// filenames.config.js +module.exports = { + js: 'js/[name].js', + jsChunk: 'js/[name].[contenthash].chunk.js', + css: 'css/[name].css', + // changing where gutenberg blocks assets are stored. + block: 'js/blocks/[name]/editor.js', + blockCSS: 'css/blocks/[name]/editor.css', +}; ``` -10up-toolkit format-js + +Alternatively you can specify the paths in `package.json` + +```json + "10up-toolkit": { + "devURL": "https://my-project.test", + "entry": { + //... + }, + "filenames": { + "block": "js/blocks/[name]/editor.js", + "blockCSS": "css/blocks/[name]/editor.css", + } + } ``` -Fixes JavaScript formatting issues via ESLint with 10up configuration. +Note that when overriding via the `filenames.config.js` you must export the filenames for all file types. + +### WordPress Editor Styles + +By default 10up-toolkit will scope any css file named `editor-styles.css` files with the +`.editor-styles-wrapper` class. Take a look at the default [postcss config](https://github.com/10up/10up-toolkit/blob/develop/packages/toolkit/config/postcss.config.js#L21) for more information. + +## Linting + +10up-toolkit comes with eslint, prettier and stylelint set up out of the box. It uses [10up's eslint config](https://github.com/10up/10up-toolkit/tree/develop/packages/eslint-config) and exposes the following commands: +`10up-toolkit lint-js`, `10up-toolkit format-js` and `10up-toolkit lint-style`. + +10up-toolkit can lint JavaScript, TypeScript and JSX without any additional configuration. It's recommended to add a npm script to your `package.json`. +```json +{ + ... + "scripts": { + "build": "10up-toolkit build", + "lint-js": "10up-toolkit lint-js", + "format-js": "10up-toolkit format-js", + "lint-style": "10up-toolkit lint-style" + } + ... +} ``` -10up-toolkit lint-js + +Then you can run `npm run lint-js` and `npm run format-js` to lint and format your codebase respectively. + +### IDE Intregration +It's not required, but you might want to create a `.eslintrc.js` and `stylelint.config.js` file at the root of your project to better integrate eslint with your code editor or to extend the linting config. + +```javascript +// .eslintrc.js +module.exports = { + extends: ['@10up/eslint-config/wordpress'], +}; ``` -Runs ESLint with 10up configuration +You can extend any of the [avaliable configs](https://github.com/10up/10up-toolkit/tree/develop/packages/eslint-config#available-eslint-configs) and enable/disable rules based on your project needs. + +```javascript +// stylelint.config.js +const config = { + extends: ['@10up/stylelint-config'], +}; +module.exports = config; ``` -10up-toolkit lint-style + +### Choosing what to lint + +10up-toolkit will lint/format any JavaScript or TypeScript file in your source code directory, you can customize this behavior in two ways: + +- Specify the directory manually `10up-toolkit lint-js src/` +- Create a `.eslintignore` + +```ignore +# Don't forget to exclude node_module and dist/build dirs +node_modules +build +dist + +path-to-code-to-be-ignored/* + ``` -Runs Stylelint with 10up configuration. +### Setting up Husky and Lint-Staged + +We also strongly recommend that you set up `lint-staged` and `husky` to automate linting your code on every commit. +First, create a `.lintstagedrc.json` file +```json +{ + "*.css": [ + "10up-toolkit lint-style" + ], + "*.[tj]s": [ + "10up-toolkit lint-js" + ], + "*.[tj]sx": [ + "10up-toolkit lint-js" + ], + // If you have php and phpcs + "*.php": [ + "./vendor/bin/phpcs --extensions=php --warning-severity=8 -s" + ] +} ``` -10up-toolkit test-unit-jest + +This will instruct lint-staged to run 10up-toolkit to link css, js and jsx files for the staged files in your commit. + +To set up git hooks with husky, create a `.husky` dir and a bash script for the git hooks you want, for example to run lint-staged +on `pre-commit`, create a `pre-commit` bash script with the following contents: + +```bash +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx lint-staged ``` -Runs Jest on current project. +Under the `.husky` dir, also add a `.gitgnore` file with the following contents: +```ignore +_ ``` -10up-toolkit check-engines + +Then, finally add the husky and lint-staged deps to your project + +```bash +npm install --save-dev husky lint-staged ``` -Verify the Node and npm satisfy minimum `package.json` versions. +Whenever you commit your code, husky will run lint-staged which will trigger the appropriate commands to lint the staged files and if any of the commands fails, your commit will be aborted. -*Project is a fork of [wp-scripts](https://github.com/WordPress/gutenberg/tree/trunk/packages/scripts)* +### VSCode Integration -## Configuration and Extension +It's strongly recommended to enable VSCode settings to format your JavaScript code on save. To do so, make sure you have the [vscode-eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) extension and add the following settings to your vscode config: -Under the hood 10up-toolkit uses Webpack, Postcss, Stylelint, Jest, Babel, and Eslint. By default the package uses 10up standard configurations for all of these tools. However, configuration can be overrided or extended for each tool. +```json + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true, + }, + "[javascript]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "[typescript]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, +``` +10up's eslint config integrated with prettier through a eslint plugin so having the vscode prettier extension is not needed and in fact, it must be disabled to avoid conflicts when saving and formatting the code. +## Authoring Libraries/Packages -### Entry points +10up-toolkit leverages standard package.json fields when running in package mode. Below is a list of all fields 10up-toolkit supports and how it's used. -This package uses Webpack under the hood and uses the following entry points: -``` -{ - admin: './assets/js/admin/admin.js', - blocks: './includes/blocks/blocks.js', - frontend: './assets/js/frontend/frontend.js', - shared: './assets/js/shared/shared.js', - styleguide: './assets/js/styleguide/styleguide.js', - - 'admin-style': './assets/css/admin/admin-style.css', - 'editor-style': './assets/css/frontend/editor-style.css', - 'shared-style': './assets/css/shared/shared-style.css', - style: './assets/css/frontend/style.css', - 'styleguide-style': './assets/css/styleguide/styleguide.css' -} -``` +- **name**: It's used to generate a valid library name to expose the library via a global variable (for UMD builds). +We recommend always specifying `libraryName` manually when creating UMD builds via `--name=your-library-name` or `10up-toolkit.libraryName` config. +- **source**: It's used to define your package entry point. +- **main**: Where the bundled JavaScript should go. Note that this field is used by NPM to specify your package entry point for consumption. +- **style**: If set, will define where the CSS will be generated. +- **umd:main** or **unpkg**: 10up-toolkit generates a separate umd build by default. This field is used by 10up-toolkit to specify where the UMD bundle should go. The benefit of generating a separate UMD bundle is to avoid including boilerplate code. -To override you will need to define `10up-toolkit.entry` in your `package.json` file. For example: ```json { + "name": "your-package-name", + "version": "1.0.0", + "main": "./dist/index.js", + "source": "./src/index.js", + "style": "./dist/index.css", + "umd:main": "./dist/index.umd.js", + "scripts": { + "build": "10up-toolkit build", + "dev": "10up-toolkit build --watch" + }, "10up-toolkit": { - "entry": { - "myEntry": ... - } - ... + "libraryName": "MyLibraryName" } } ``` -### WordPress Dependecy Extraction +Then, the following code: +```javascript +// src/index.js +import './styles.css'; -10up scripts will automatically run the [dependecy extraction plugin](https://developer.wordpress.org/block-editor/packages/packages-dependency-extraction-webpack-plugin/). If you don't want to run the dependecy extraction plugin you can disable it by setting a ENV var `TENUP_NO_EXTERNAL` or by setting the `wpDependencyExternals` setting to false in package.json. +export default () => { /* my awesome js code */}; +``` -```json -{ - "10up-toolkit": { - "entry": { - "myEntry: ... - }, - "wpDependencyExternals": false - ... - } -} +will generate a `index.js`, `index.umd.js` and a `index.css` file in the `dist` folder after running `npm run build`. + +### Undertanding Package Mode + +It's important to understand how 10up-toolkit behaves when running in package mode. First and foremost, core-js polyfills **will not** be added automatically. + +If you package should support older browsers and you want to include core-js polyfills you will need to declare core-js as a dependency, and manually include the polyfills you need, e.g: + +```javascript +import 'core-js/es/array/from'; +import 'core-js/web/dom-collections'; ``` +The second difference is that 10up-toolkit **wil not** include the dependencies (or peer dependencies) in the final bundle. +The reason for this is that, it's responsibility of the consumer bundle to resolve and include dependencies in the final bundle. Doing otherwise could lead to duplication of packages in the application final bundle. -### Browsersync +This behavior is inspired in [how microbundle](https://github.com/developit/microbundle/wiki/How-Microbundle-decides-which-dependencies-to-bundle) handle bundling packages. -10up Scripts starts Browsersync automatically. All you need to do is change `10up-toolkit.devURL` in your `package.json` to point to your local development URL: +## Customizations -```json -{ - "10up-toolkit": { - "devURL": "https://project.test", - ... - } -} +10up-toolkit is very extensible and pretty much all config files can be overridden by simply creating a config file at the root of your project. + +### Customizing the Webpack config +In general, we don't recommend customizing the webpack config, the default webpack config and the 10up-toolkits options should provide all that's needed +for most projects. However, in case you need to modify the webpack config you can to so by creating a `webpack.config.js` file at the root of your project. + +The example below will update the webpack config so that 10up-toolkit processes and transpiles `@vendor/your-custom-package`. This would be required you publishing an untranspiled package. + +```javascript +// webpack.config.js + +const config = require('10up-toolkit/config/webpack.config.js'); + +config.module.rules[0].exclude = + /node_modules\/(?!(@10up\/block-components)|(@vendor\/your-custom-package)\/).*/; + +module.exports = defaultConfig; ``` -### Webpack +### Customizing eslint and styling -10up-toolkit will use 10up standard Webpack configuration located in [/config/webpack.config.js](https://github.com/10up/10up-toolkit/blob/trunk/packages/toolkit/config/webpack.config.js) UNLESS you define a Webpack config file in your project e.g. you have a `webpack.config.js` in your project root. If you just need to change entry points, see the Entry Points section below. +To customize eslint, create a supported eslint config file at the root of your project. Make sure to extend the from `@10up/eslint-config` package. -Here's an example `webpack.config.js` you could add to the root of your project to extend `10up/scripts` Webpack. +If you're writing tests with jest for example, you will need to include the rules for jest. + +```javascript +// .eslintrc.js -```js -const defaultConfig = require('10up-toolkit/config/webpack.config'); module.exports = { - ...defaultConfig, - myObject: { - stuffHere: true + extends: ['@10up/eslint-config/wordpress', '@10up/eslint-config/jest'], + rules: { + /* add or modify rules here */ + } +}; +``` + +Similarly, for customizing stylelint, create a `stylelint.config.js` file. + +```javascript +// stylelint.config.js +const config = { + extends: ['@10up/stylelint-config'], + rules: { + /* add or modify rules here */ } }; + +module.exports = config; +``` + +Refer to linting docs for more information. + +### Customizing PostCSS + +To customize the postcss config, create a `postcss.config.js` at the root of your project. When overriding the postcss config, keep in mind +that the default config is exported as a **function**. + +The example below modifies the ignored list of the `editor-styles` plugin when processing the `editor-styles.css` file. + +```javascript +const baseConfig = require('10up-toolkit/config/postcss.config.js'); +const path = require('path'); + +module.exports = (props) => { + const config = baseConfig(props); + const { file } = props; + + if (path.basename(file) === 'editor-style.css') { + config.plugins['postcss-editor-styles'].ignore = [ + ...config.plugins['postcss-editor-styles'].ignore, + '.mh-personalization-segment-picker', + ]; + } + return config; +}; ``` -### ESLint +## CLI Options -10up-toolkit will use 10up standard ESLint configuration located in [/config/.eslintrc.js](https://github.com/10up/10up-toolkit/blob/trunk/packages/toolkit/config/.eslintrc.js) which extends [@10up/eslint-config](https://github.com/10up/eslint-config) UNLESS you define a ESLint config file in your project e.g. you have a `.eslintrc.js` in your project root. +10up-toolkit supports several CLI options that can be used to override settings. -### Stylelint +### Source and Output +To set the source and main/ouput path via the CLI you can use the `-i` and `-o` (or `--input` and `--output` options) -10up-toolkit will use 10up standard Stylelint configuration located in [/config/stylelint.config.js](https://github.com/10up/10up-toolkit/blob/trunk/packages/toolkit/config/stylelint.config.js) which extends [@10up/stylelint-config](https://github.com/10up/stylelint-config) UNLESS you define a Stylelint config file in your project e.g. you have a `stylelint.config.js` in your project root. +```bash +10up-toolkit build -i=src/index.js -o=dist/index.js +``` -### PostCSS +This can be useful if you have multiple entry points if you want to create a test application for your package. -10up-toolkit will use 10up standard PostCSS configuration located in [/config/postcss.config.js](https://github.com/10up/10up-toolkit/blob/trunk/packages/toolkit/config/postcss.config.js) UNLESS you define a PostCSS config file in your project e.g. you have a `postcss.config.js` in your project root. +```javascript +// app.js +// index is the entry point of the package +import { Accordion } from './index'; -### Babel +new Accordion('.accordion'); +``` -10up-toolkit will use 10up standard Babel configuration of [@10up/babel-preset-default](https://github.com/10up/babel-preset-default) UNLESS you define a Babel config file in your project e.g. you have a `.babelrc` in your project root. +Then you can instruct 10up-toolkit to use your app.js file and spin up a dev server in a separate npm script. +```json +"start": "10up-toolkit start -i=src/app.js --dev-server", +``` + +### Dev Server + +
This option was added in 10up-toolkit 1.0.8+ +The `--dev-server` allows you to quickly spin up a development server. The default port is 8000 and can be changed via `--port`. + +If you need to override the default html template, create a `index.html` file under a `public` dir. + +```html + + + + + +