github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/README.md (about) 1 # Admin UI 2 3 This directory contains the client-side code for CockroachDB's web-based admin 4 UI, which provides details about a cluster's performance and health. See the 5 [Admin UI docs](https://www.cockroachlabs.com/docs/stable/explore-the-admin-ui.html) 6 for an expanded overview. 7 8 ## Getting Started 9 10 To start developing the UI, be sure you're able to build and run a CockroachDB 11 node. Instructions for this are located in the top-level README. Every Cockroach 12 node serves the UI, by default on port 8080, but you can customize the port with 13 the `--http-port` flag. If you've started a node with the default options, 14 you'll be able to access the UI at <http://localhost:8080>. 15 16 Our UI is compiled using a collection of tools that depends on 17 [Node.js](https://nodejs.org/) and are managed with 18 [Yarn](https://yarnpkg.com), a package manager that offers more deterministic 19 package installation than NPM. NodeJS 6.x and Yarn 1.7.0 are known to work. 20 [Chrome](https://www.google.com/chrome/), Google's internet browser. Unit tests 21 are run using Chrome's "Headless" mode. 22 23 With Node and Yarn installed, bootstrap local development by running `make` in 24 this directory. This will run `yarn install` to install our Node dependencies, 25 run the tests, and compile the assets. Asset compilation happens in two steps. 26 First, [Webpack](https://webpack.github.io) runs the TypeScript compiler and CSS 27 preprocessor to assemble assets into the `dist` directory. Then, we package 28 those assets into `embedded.go` using 29 [go-bindata](https://github.com/kevinburke/go-bindata). When you later run `make 30 build` in the parent directory, `embedded.go` is linked into the `cockroach` 31 binary so that it can serve the admin UI when you run `cockroach start`. 32 33 ## Developing 34 35 When making changes to the UI, it is desirable to see those changes with data 36 from an existing cluster without rebuilding and relaunching the cluster for each 37 change. This is useful for rapidly visualizing local development changes against 38 a consistent and realistic dataset. 39 40 We've created a simple NodeJS proxy to accomplish this. This server serves all 41 requests for web resources (JavaScript, HTML, CSS) out of the code in this 42 directory, while proxying all API requests to the specified CockroachDB node. 43 44 To use this proxy, in Cockroach's root directory run: 45 ```shell 46 $ make ui-watch TARGET=<target-cluster-http-uri> 47 ``` 48 49 or, in `pkg/ui` run: 50 ```shell 51 $ make watch TARGET=<target-cluster-http-uri> 52 ``` 53 54 then navigate to `http://localhost:3000` to access the UI. 55 56 To proxy to a cluster started up in secure mode, in Cockroach's root directory run: 57 ```shell 58 $ make ui-watch-secure TARGET=<target-cluster-https-uri> 59 ``` 60 61 or, in `pkg/ui` run: 62 ```shell 63 $ make watch-secure TARGET=<target-cluster-https-uri> 64 ``` 65 66 then navigate to `https://localhost:3000` to access the UI. 67 68 While the proxy is running, any changes you make in the `src` directory will 69 trigger an automatic recompilation of the UI. This recompilation should be much 70 faster than a cold compile—usually less than one second—as Webpack can reuse 71 in-memory compilation artifacts from the last compile. 72 73 If you get cryptic TypeScript compile/lint failures upon running `make` that 74 seem completely unrelated to your changes, try removing `yarn.installed` and 75 `node_modules` before re-running `make` (do NOT run `yarn install` directly). 76 77 Be sure to also commit modifications resulting from dependency changes, like 78 updates to `package.json` and `yarn.lock`. 79 80 ### DLLs for speedy builds 81 82 To improve Webpack compile times, we split the compile output into three 83 bundles, each of which can be compiled independently. The feature that enables 84 this is [Webpack's DLLPlugin](https://webpack.js.org/plugins/dll-plugin/), named 85 after the Windows term for shared libraries ("**d**ynamic-**l**ink 86 **l**ibraries"). 87 88 Third-party dependencies, which change infrequently, are contained in the 89 [vendor DLL]. Generated protobuf definitions, which change more frequently, are 90 contained in the [protos DLL]. First-party JavaScript and TypeScript are 91 compiled in the [main app bundle], which is then "linked" against the two DLLs. 92 This means that updating a dependency or protobuf only requires rebuilding the 93 appropriate DLL and the main app bundle, and updating a UI source file doesn't 94 require rebuilding the DLLs at all. When DLLs were introduced, the time required 95 to start the proxy was reduced from over a minute to under five seconds. 96 97 DLLs are not without costs. Notably, the development proxy cannot determine when 98 a DLL is out-of-date, so the proxy must be manually restarted when dependencies 99 or protobufs change. (The Make build system, however, tracks the DLLs' 100 dependencies properly, so a top-level `make build` will rebuild exactly the 101 necessary DLLs.) DLLs also make the Webpack configuration rather complicated. 102 Still, the tradeoff seems well worth it. 103 104 ## CCL Build 105 106 In CCL builds, code in `pkg/ui/ccl/src` overrides code in `pkg/ui/src` at build 107 time, via a Webpack import resolution rule. E.g. if a file imports 108 `src/views/shared/components/licenseType`, it'll resolve to 109 `pkg/ui/src/views/shared/components/licenseType` in an OSS build, and 110 `pkg/ui/ccl/src/views/shared/components/licenseType` in a CCL build. 111 112 CCL code can import OSS code by prefixing paths with `oss/`, e.g. 113 `import "oss/src/myComponent"`. By convention, this is only done by a CCL file 114 importing the OSS version of itself, e.g. to render the OSS version of itself 115 when the trial period has expired. 116 117 ## Running tests 118 119 To run the tests outside of CI: 120 121 ```shell 122 $ make test 123 ``` 124 125 ## Viewing bundle statistics 126 127 The regular build also produces a webpage with a report on the bundle size. 128 Build the app, then take a look with: 129 130 ```shell 131 $ make build 132 $ open pkg/ui/dist/stats.ccl.html 133 ``` 134 135 Or, to view the OSS bundle: 136 137 ```shell 138 $ make buildoss 139 $ open pkg/ui/dist/stats.oss.html 140 ``` 141 142 ## Bundling fonts 143 144 To comply with the SIL Open Font License, we have reproducible builds of our WOFF 145 font bundles based on the original TTF files sourced from Google Fonts. 146 147 To rebuild the font bundles (perhaps to bring in an updated version of a typeface), 148 simply run `make fonts` in the UI directory (or `make ui-fonts` elsewhere). This 149 requires `fontforge` to be available on your system. Then validate the updated 150 fonts and commit them. 151 152 To add a new typeface, edit the script `scripts/font-gen` to fetch and convert it, 153 and then add it to `styl/base/typography.styl` to pull it into the bundle. 154 155 ## Managing dependencies 156 157 The NPM registry (and the Yarn proxy in front of it) have historically proven 158 quite flaky. Errors during `yarn install` were the leading cause of spurious CI 159 failures in the first half of 2018. 160 161 The solution is to check our JavaScript dependencies into version control, like 162 we do for our Go dependencies. Checking in the entire node_modules folder is a 163 non-starter: it clocks in at 230MB and 28k files at the time of writing. 164 Instead, we use a Yarn feature called the [offline mirror]. We ship a [.yarnrc] 165 file that instructs Yarn to save a tarball of each package we depend on in the 166 [yarn-vendor] folder. These tarballs are then checked in to version control. To 167 avoid cluttering the main repository, we've made the yarn-vendor folder a Git 168 submodule that points at the [cockroachdb/yarn-vendored] repository. 169 170 ### Adding a dependency 171 172 Let's pretend you want to add a dependency on `left-pad`. Just use `yarn add` 173 like you normally would: 174 175 ```bash 176 $ cd $GOPATH/src/github.com/cockroachdb/cockroach/pkg/ui 177 $ yarn add FOO 178 ``` 179 180 When Yarn finishes, `git status` will report something like this: 181 182 ```bash 183 $ git status 184 Changes not staged for commit: 185 modified: pkg/ui/package.json 186 modified: pkg/ui/yarn-vendor (untracked content) 187 modified: pkg/ui/yarn.lock 188 ``` 189 190 The changes to package.json and yarn.lock are the normal additions of the new 191 dependency information to the manifest files. The changes to yarn-vendor are 192 unique to the offline mirror mode. Let's look more closely: 193 194 ```bash 195 $ git -C yarn-vendor status 196 Untracked files: 197 left-pad-1.3.0.tgz 198 ``` 199 200 Yarn has left you a tarball of the new dependency. Perfect! If you were adding 201 a more complicated dependency, you'd likely see some transitive dependencies 202 appear as well. 203 204 The process from here is exactly the same as updating any of our other vendor 205 submodules. Make a new branch in the submodule, commit the new tarball, and push 206 it: 207 208 ```bash 209 $ cd yarn-vendor 210 $ git checkout -b YOURNAME/add-left-pad 211 $ git add . 212 $ git commit -m 'Add left-pad@1.3.0' 213 $ git push origin add-left-pad 214 ``` 215 216 Be sure to push to [cockroachdb/yarn-vendored] directly instead of a personal 217 fork. Otherwise TeamCity won't be able to find the commit. 218 219 Then, return to the main repository and commit the changes, including the new 220 submodule commit. Push that and make a PR: 221 222 ```bash 223 $ cd .. 224 $ git checkout -b add-left-pad 225 $ git add pkg/ui 226 $ git commit -m 'ui: use very smart approach to pad numbers with zeros' 227 $ git push YOUR-REMOTE add-left-pad 228 ``` 229 230 This time, be sure to push to your personal fork. Topic branches are not 231 permitted in the main repository. 232 233 When your PR has been approved, please be sure to merge your change to 234 yarn-vendored to master and delete your topic branch: 235 236 ```bash 237 $ cd yarn-vendor 238 $ git checkout master 239 $ git merge add-left-pad 240 $ git push origin master 241 $ git push origin -d add-left-pad 242 ``` 243 244 This last step is extremely important! Any commit in yarn-vendored that is 245 referenced by the main repository must remain forever accessible, or it will be 246 impossible for future `git clone`s to build that version of Cockroach. GitHub 247 will garbage collect commits that are not accessible from any branch or tag, and 248 periodically, someone comes along and cleans up old topic branches in 249 yarn-vendored, potentially removing the only reference to a commit. By merging 250 your commit on master, you ensure that your commit will not go missing. 251 252 ### Verifying offline behavior 253 254 Our build system is careful to invoke `yarn install --offline`, which instructs 255 Yarn to exit with an error if it would need to reach out to the network. Running 256 CI on your PR is thus sufficient to verify that all dependencies have been 257 vendored correctly. 258 259 You can perform the verification locally if you'd like, though: 260 261 ```bash 262 $ cd $GOPATH/src/github.com/cockroachdb/cockroach/pkg/ui 263 $ rm -r node_modules yarn.installed 264 $ yarn cache clean 265 $ make 266 ``` 267 268 If `make` succeeds, you've vendored dependencies correctly. 269 270 ### Removing a dependency 271 272 To remove a dependency, just run `yarn remove`. 273 274 Note that removing a dependency will not remove its tarball from the yarn-vendor 275 folder. This is not as bad as it sounds. When Git fetches submodules, it always 276 performs a full clone, so it would wind up downloading deleted tarballs anyway 277 when it fetched older commits. 278 279 TODO(benesch): Yarn's offline mode has an additional option, 280 `yarn-offline-mirror-pruning`, that cleans up removed dependencies' tarballs. 281 Look into using this once [dcodeIO/protobuf.js#716] is resolved. At the moment, 282 ProtobufJS tries to install some dependencies at runtime by invoking `npm 283 install` itself (!); we avoid this by running `yarn install` on its behalf, but 284 this means two separate packages share the same yarn-vendor folder and this 285 confuses Yarn's pruning logic. 286 287 If the size of the yarn-vendored repository becomes problematic, we can look 288 into offloading the large files into something like [Git LFS]. This is 289 contingent upon resolving the above TODO. 290 291 [cockroachdb/yarn-vendored]: https://github.com/cockroachdb/yarn-vendored 292 [dcodeIO/protobuf.js#716]: https://github.com/dcodeIO/protobuf.js#716 293 [main app bundle]: ./webpack.app.js 294 [Git LFS]: https://git-lfs.github.com 295 [offline mirror]: https://yarnpkg.com/blog/2016/11/24/offline-mirror/ 296 [protos DLL]: ./webpack.protos.js 297 [vendor DLL]: ./webpack.vendor.js 298 [.yarnrc]: ./yarnrc 299 [yarn-vendor]: ./yarn-vendor