Upgrading Persona Bar Components Guide
Overview
For version 9.3 of DNN Platform all the persona bar components in the Persona Bar have been upgraded to React 16. The Persona Bar has also been updated to use the new DNN React Common components, which have also been upgraded to React 16.
If you currently have any Persona Bar components that you have developed you will need to update them to the latest version of React as well as update to the latest DNN React Common components. This post is a guide to help you accomplish that.
How Does the Persona Bar Work?
Currently the Persona Bar loads JQuery and RequireJS. It also loads a bundle called export-bundle.js. This bundle contains React and all the supporting components. When a menu item in the Persona Bar is clicked RequireJS dynamically pulls the bundle file for the requested menu item. Once the bundle is loaded it executes using the dependencies that were loaded by export-bundle.js.
There are several tools that will need to be installed on your machine to upgrade a Persona Bar project. You will need node, yarn at a minimum. I also recommend installing npm-check-updates and react-codemod as they make updating the package references really easy.
Node JS
You can download and install Node JS from [here][https://nodejs.org/].
Yarn
Once you have node installed, you can install yarn. Use the instructions here to install yarn on your platform.
NPM Check Updates
Run the following from a command prompt
yarn global add npm-check-updates
React Code Mod
Finally you will need to install react-codemod. This is a GitHub repository that allows you to run various commands on React projects. To install react-codemod
yarn global add jscodeshift
git clone https://github.com/reactjs/react-codemod.git or download a zip file from https://github.com/reactjs/react-codemod/archive/master.zip
- Run
yarn install in the react-codemod directory
jscodeshift -t <codemod-script> <path>
codemod-script - path to the transform file, see available scripts below;
path - files or directory to transform;
- use the
-d option for a dry-run and use -p to print the output for comparison;
- use the
--extensions option if your files have different extensions than .js (for example, --extensions js,jsx);
- if you use flowtype, you might also need to use
--parser=flow;
- see all available jscodeshift options.
You can view all the possible react-codemod scripts at the GitHub repository.
Start Updating Your Component
Once you have all the tools installed go into your component
Check for Updates
Once you are in the correct folder it is time to start updating the component.
- Remove the existing
yarn.lock file
- Check for updates
yarn upgrade
ncu -u
- Remove existing babel plugins:
yarn remove babel-core babel-plugin-transform-object-assign babel-plugin-transform-object-rest-spread babel-preset-es2015 babel-preset-react
- Add new babel plugins:
yarn add @babel/core@^7.1.6 @babel/plugin-proposal-object-rest-spread@^7.0.0 @babel/plugin-transform-object-assign@^7.0.0 @babel/preset-env@^7.1.6 @babel/preset-react@^7.0.0 -D
- Add
prop-types, webpack-cli
yarn add prop-types@^15.6.2 webpack-cli@^3.1.2 -D
- Update the
.babelrc file. Just copy and paste the following:
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-transform-object-assign",
"@babel/plugin-proposal-object-rest-spread",
"react-hot-loader/babel"
],
"env": {
"production": {
"plugins": [
"transform-react-remove-prop-types"
]
}
}
}
- Update the
.eslintrc.js file.
- Add the
"settings" section
...
"extends": ["eslint:recommended", "plugin:react/recommended"],
"settings": {
"react": {
"version": "16"
}
},
...
- Set the
parserOptions and ecmaVersion
...
"parserOptions": {
"ecmaFeatures": {
"jsx": true,
"arrowFunctions": true,
"blockBindings": true,
"classes": true,
"defaultParams": true,
"destructuring": true,
"forOf": true,
"generators": true,
"modules": true,
"objectLiteralComputedProperties": true,
"regexUFlag": true,
"regexYFlag": true,
"spread": true,
"superInFunctions": false,
"templateStrings": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
...
-
Upgrade the webpack.config.js file There are several instructions online about upgrading webpack configuration files to webpack 4. This will only be a brief overview. You can also look at the webpack.config.js file in Dnn.AdminExperience\Extensions\Manage\Dnn.PersonaBar.Roles\Roles.Web for reference.
- Add
optimization
...
entry: "./src/main.jsx",
optimization: {
minimize: isProduction
},
...
- Resolve the
output path
...
output: {
path: path.resolve("../admin/personaBar/scripts/bundles/"),
...
},
...
- Update the
module section to remove loaders and preLoaders. The final section should look similar to
module: {
rules: [
{ test: /\.(js|jsx)$/, enforce: "pre", exclude: /node_modules/, loader: "eslint-loader", options: { fix: true } },
{ test: /\.(js|jsx)$/ , exclude: /node_modules/, loaders: ["babel-loader"] },
{ test: /\.(less|css)$/, loader: "style-loader!css-loader!less-loader" },
{ test: /\.(ttf|woff)$/, loader: "url-loader?limit=8192" },
{ test: /\.(gif|png)$/, loader: "url-loader?mimetype=image/png" },
{ test: /\.woff(2)?(\?v=[0-9].[0-9].[0-9])?$/, loader: "url-loader?mimetype=application/font-woff" },
{ test: /\.(ttf|eot|svg)(\?v=[0-9].[0-9].[0-9])?$/, loader: "file-loader?name=[name].[ext]" },
]
},
- Alter the
resolve section
...
resolve: {
extensions: [".js", ".json", ".jsx"],
modules: [
path.resolve("./src"), // Look in src first
path.resolve("./node_modules") // Last fallback to node_modules
]
},
...
- Remove the
UglifyJsPlugin and DedupePlugin from the plugins section
-
Install all the dependencies and regenerate the yarn.lock file
yarn install
- Alter the
jsx files to use PropTypes instead of React.PropTypes This is where the react-codemod script comes in handy. At the command prompt navigate to where you installed the react-codemod repository and run
jscodeshift -t react-codemod/transforms/React-PropTypes-to-prop-types.js <path>
Reaplacing the <path> with the path to your components src directory. For example to run this on the Roles component, where the Dnn.AdminExperience project is located at C:\git\Dnn.AdminExperience, you would run
jscodeshift -t react-codemod/transforms/React-PropTypes-to-prop-types.js C:\git\Dnn.AdminExperience\Extensions\Manage\Dnn.PersonaBar.Roles\Roles.Web --extensions js,jsx
If you want to see what files the script is going to alter then you can add the options -d -p to the command.
-
Build the component and fix any errors and warnings that appear.
yarn run build
Some of the most common errors that appear are:
- Do not use findDOMNode
- string refs are not allowed
- componentWillMount is deprecated
- componentWillReceiveProps is deprecated
To correct the string refs are not allowed and the findDOMNode error please refer to the following post. Rule proposal: warn against using findDOMNode()
To correct the deprecated react lifecycle errors please refer to the following post. Migrating from Legacy Lifecycles
- Test your component You should have a component that builds now. Once the bundle is built, copy it into a local DNN instance at the proper file location and attempt to access it from the Persona Bar. Once the component comes up, test everything related to that component.
Upgrading to the Latest Dnn.React.Common Components Library
Why was the Library Restructured
The library was restructured to make development against the react components simpler as well as to save space due to the node_modules folder being installed on every single component.
The component library is now being published on npm.js so you no londer have to add references to myget.
Installation
yarn add @dnnsoftware/dnn-react-common -D
Update the webpack.config.js
If you are using the DNN React Common components as external references you will need to update your webpack.config.js file to use the new path.
externals: require("@dnnsoftware/dnn-react-common/WebpackExternals"),
Update your components
Search for all files with from “dnn- Go to each file and replace the import statements with a import like the following using the components you are replacing
Import { SvgIcons, Button, Label, SingleLineTextBoxWithError } from “@dnnsoftware/dnn-react-common”;
Update your CSS References
Anywhere you reference the old dnn-global-styles component you will need to replace that reference with the following:
@import "~@dnnsoftware/dnn-react-common/styles/index";
Things that changed
If you get a JavsScript error during rendering of your component that says: Error: Minified React error #130
It means that one of the components you have referenced has an incorrect name. A few of the components had to have their names changed. Take a look at the following list:
Collapse -> Collapsible or CollapsibleRow
DropDown -> Dropdown
SvgIcons -> You must prefix the icon name with SvgIcons. E.g. ArrowBack -> SvgIcons.ArrowBack
Tabs -> DnnTabs OverflowWrapper -> TextOverflowWrapper
Closing Statements
This seems like an awful lot to go through to upgrade the projects. However, these steps go fairly quickly and the effort is worth it. Going forward the community will need to decide how often React and the supporting components will be updated. We will need to do this fairly often so we do not have to go through this large update again!