Skip to content

Commit

Permalink
DOC Update changelog with breaking js changes
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli committed Dec 20, 2022
1 parent fb356c1 commit 2fd6470
Showing 1 changed file with 217 additions and 0 deletions.
217 changes: 217 additions & 0 deletions en/04_Changelogs/5.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ title: 5.0.0 (unreleased)
- [Dependency changes](#dependency-changes)
- [General changes](#dep-general)
- [TinyMCE upgraded from 4 to 6](#tinymce6)
- [Front-end build stack upgrades](#front-end)
- [Webpack config](#webpack-config)
- [Updated javascript dependencies](#updated-javascript-dependencies)
- [Common upgrade patterns](#common-upgrade-patterns)
- [Breaking changes in _our_ javascript components or API](#js-api)
- [Features and enhancements](#features-and-enhancements)
- [Other features](#other-features)
- [Bugfixes](#bugfixes)
Expand Down Expand Up @@ -212,6 +217,218 @@ There were a lot more changes than just those, so you may want to also check out
- [List of toolbar buttons available for TinyMCE 6](https://www.tiny.cloud/docs/tinymce/6/available-toolbar-buttons/)
- [Create a plugin](https://www.tiny.cloud/docs/tinymce/6/creating-a-plugin/)

## Front-end build stack upgrades {#front-end}

[info]
"Front-end" in this section refers to the javascript and css in the CMS. It doesn't have any impact on your website's public-facing front-end.
[/info]

We've upgraded the front-end build stack for the CMS, along with most of the javascript dependencies.

### Webpack config

The [@silverstripe/webpack-config](https://www.npmjs.com/package/@silverstripe/webpack-config) and [@silverstripe/eslint-config](https://www.npmjs.com/package/@silverstripe/eslint-config) NPM libraries, along with the build stack for all supported modules, has been updated to be compatible with node 18 and webpack 5. This will only impact you if your module or project uses one or both of those NPM packages - you will need to make sure you upfate your own dependencies to be compatible with them, along with the dependencies listed below if you use them.

With this comes a change to the API for `@silverstripe/webpack-config`. There is a new (optional) abstracted API for declaring the webpack config for transpiling the javascript and css for your CMS customisations, which has been documented extensively in the readme for that library.

You can continue to use the old API if you want to, but you will need to account for the following breaking changes:

- The `UglifyJsPlugin` is no longer used to remove comments from transpiled code. Refer to the `optimisation` config in [the abstracted JavascriptWebpackConfig class](https://github.com/silverstripe/webpack-config/blob/2/configMeta/javascriptWebpackConfig.js) instead.
- `script-loader`, `file-loader`, and `url-loader` have all been replaced with the relevant [webpack assets](https://webpack.js.org/guides/asset-modules/) configuration.
- `ExtractTextPlugin` and its associated configuration has been replaced with `MiniCssExtractPlugin`.
- Supported browser configuration has been replaced with setting an appropriate [browserslist](https://browsersl.ist) configuration in your `package.json` file.

### Updated javascript dependencies

The following javascript dependencies (which are used in the CMS, and may impact your customisations) have been updated to new major versions, or replaced:

|old package and version|new package and version|upgrade guide|
|---|---|---|
|apollo-client `^2.3.1`|@apollo/client `^3.7.1`|[upgrade guide][apollo-guide]|
|apollo-cache-inmemory `^1.2.1`|@apollo/client `^3.7.1`|[upgrade guide][apollo-guide]|
|apollo-link `^1.2.2`|@apollo/client `^3.7.1`|[upgrade guide][apollo-guide]|
|apollo-link-batch-http `^1.2.1`|@apollo/client `^3.7.1`|[upgrade guide][apollo-guide]|
|apollo-link-error `^1.0.9`|@apollo/client `^3.7.1`|[upgrade guide][apollo-guide]|
|apollo-link-http `^1.5.4`|@apollo/client `^3.7.1`|[upgrade guide][apollo-guide]|
|apollo-link-state `^0.4.1`|@apollo/client `^3.7.1`|[upgrade guide][apollo-guide]|
|graphql `^14.0.0`|graphql `^16.6.0`|[github changelog][graphql-changelog]|
|merge `^1.2.1`|merge `^2.1.1`|N/A|
|react `^16.6.1`|react `^18.2.0`|[upgrade guide][react-guide]|
|react-apollo `^2.1.0`|@apollo/client `^3.7.1`|[upgrade guide][apollo-guide]|
|react-redux `^5.0.7`|react-redux `^8.0.5`|[github changelog][react-redux-changelog]|
|react-router `^4.4.0`|react-router `^6.4.2`|[upgrade guide][react-router-guide]|
|react-router-config `^4.4.0`|react-router `^6.4.2`|[upgrade guide][react-router-guide]|
|react-router-dom `^4.4.0`|react-router-dom `^6.4.2`|[upgrade guide][react-router-guide]|
|react-select `^1.3`|react-select `^5.5.8`|[upgrade guides][react-select-guide]|
|redux-form `^7.4.2`|redux-form `^8.3.8`|[github changelogs][react-form-changelog]|
|validator `^6.1.0`|validator `^13.7.0`|[changelog][validator-changelog]|
|dropzone `^5.7.2`|dropdown `^6.0.0-beta.2`|[changelog][dropzone-changelog]|

[apollo-guide]: https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration
[graphql-changelog]: https://github.com/graphql/graphql-js/releases/tag/v16.0.0
[react-guide]: https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
[react-router-guide]: https://github.com/remix-run/react-router/blob/main/docs/upgrading/v5.md
[react-select-guide]: https://react-select.com/upgrade
[react-form-changelog]: https://github.com/redux-form/redux-form/releases/tag/v8.0.0
[validator-changelog]: https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md
[dropzone-changelog]: https://github.com/dropzone/dropzone/blob/main/CHANGELOG.md
[react-redux-changelog]: https://github.com/reduxjs/react-redux/releases

### Common upgrade patterns

While upgrading core modules, there were a few common patterns we found that might be useful for you. Those are listed here for your convenience.

#### `ReactDOM.render()` replaced with `ReactDOM.createRoot().render()`

If you are injecting a React component in a section of the CMS that uses entwine, you likely have something like this:

```js
import ReactDOM from 'react-dom';

$('.grid-field').entwine({
onmatch() {
ReactDOM.render(<MyComponent />, this[0]);
},

onunmatch() {
const container = this[0];
if (container) {
ReactDOM.unmountComponentAtNode(container);
}
},
});
```

Instead of using `ReactDOM.render()`, you should now call `ReactDOM.createRoot().render()` - but if you try to use `createRoot()` multiple times on the same element, react will complain, so you'll want to keep a reference to the root you made the first time. The above example turns into this:

```js
import ReactDOM from 'react-dom';

$('.grid-field').entwine({
ReactRoot: null,

onmatch() {
let root = this.getReactRoot();
if (!root) {
root = ReactDOM.createRoot(this[0]);
}
root.render(<MyComponent />);
this.setReactRoot(root);
},

onunmatch() {
const root = this.getReactRoot();
if (root) {
root.unmount();
this.setReactRoot(null);
}
},
});
```

#### React route paths are now relative to their parent routes

The update to `react-router` has changed the paths for routes in react-only sections of the CMS (such as /admin/assets) to be relative to the parent routes. If you have a custom react CMS section, you'll need to make sure you're using the relative path. This is included as `reactRoutePath` in the array returned by `LeftAndMain::getClientConfig()` by default, but you may need to double check your custom admin section is returning the correct value.

Then, in your javascript implementation where you are adding your route to the `ReactRouteRegister`, simple change your route's path from using the `url` key to use the new `reactRoutePath` key.

```diff
import ConfigHelpers from 'lib/Config';
import reactRouteRegister from 'lib/ReactRouteRegister';
import MyAdmin from './MyAdmin';

document.addEventListener('DOMContentLoaded', () => {
const sectionConfig = ConfigHelpers.getSection('MyAdmin');
reactRouteRegister.add({
- path: sectionConfig.url,
+ path: sectionConfig.reactRoutePath,
component: MyAdminComponent,
});
});
```

#### `react-router` no longer has a `withRouter` HOC

In the old version of react-router, the `withRouter` Higher Order Component could be used to wrap your component which needs access to the router and its functionality.

This has been removed. The ideal way to upgrade will be to rewrite your components to work with the new API as per the upgrade guide referenced in the table above.

If you don't have time or resources to rewrite your components, we do have a temporary solution for you - but bear in mind that this is just kicking the can down the road. You _will_ have to upgrade to use the new react-router API eventually.

Silverstripe CMS 5 includes a replacement `withRouter` Higher Order Component that you can use until you have the resources necessary to upgrade properly. It passes different props than the old one did, so you will still need to make some changes. For example:

```js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';

class MyAdmin extends Component {
// Your implementation here
}

MyAdmin.propTypes = {
location: PropTypes.shape({
pathname: PropTypes.string,
query: PropTypes.object,
search: PropTypes.string,
}),
match: PropTypes.shape({
params: PropTypes.shape({
view: PropTypes.string,
id: PropTypes.number,
}),
}),
history: PropTypes.object,
};

export default withRouter(MyAdmin);
```

The above expects the `match` and `history` props from the `withRouter` HOC. These are no longer passed. What's more, you don't have to declare your own proptypes, we've exported that for you. The above now becomes this:

```js
import React, { Component } from 'react';
import withRouter, { routerPropTypes } from 'lib/withRouter';

class MyAdmin extends Component {
// Your implementation here
}

MyAdmin.propTypes = {
router: routerPropTypes,
};

export default withRouter(MyAdmin);
```

The new props that our `withRouter` HOC passes in is a single prop called `router` which has the following `PropTypes` definition:

```js
PropTypes.shape({
location: PropTypes.shape({
pathname: PropTypes.string,
query: PropTypes.object,
search: PropTypes.string,
}),
navigate: PropTypes.func,
params: PropTypes.object,
})
```

`router.params` is a one-to-one replacement for the old `match.params`, and `router.location` is a one-to-one replacement for the old `location` prop.

Refer to the upgrade guide from the table above to learn how to replace the old `history` prop with the new `router.navigate` prop.

### Breaking changes in _our_ javascript components or API {#js-api}

For the most part we were able to retain our existing API and not make any drastic changes to our react components through upgrading our dependencies, but there was one notable exception.

To conform with the API changes in the new version of `react-select`, the `TreeDropdownField` component has changed considerably, and the `TreeDropdownFieldMenu` component has been removed entirely.

If you were customising the `TreeDropdownField` React component at all or injecting a custom version of `TreeDropdownFieldMenu`, you will want to take a look at the source code for the `TreeDropdownField` component and maybe have a look at the upgrade guides for `react-select` referenced in the table above to see what changes you need to make.

Some of the css classes related to `TreeDropdownField` have also changed, as a result of the upgrade to `react-select`.

## Features and enhancements {#features-and-enhancements}

### Extension changes
Expand Down

0 comments on commit 2fd6470

Please sign in to comment.