--- myst: html_meta: "description": "Volto add-ons development training module 7, Advanced topics" "property=og:description": "Volto add-ons development training module 7" "property=og:title": "Volto add-ons development object Add-ons advanced topics" "keywords": "Volto" --- # Add-ons - advanced topics ## Q&A Is it possible to customize Volto with an add-on? : Yes, the code path used is the same, so you can use the same convention. Make sure you have the `src/customizations` folder inside your add-on. And remember, the customization resolution order follows the same order as the add-ons listed in the `addons` key of `package.json` inside the project. Can I customize an add-on? : You can customize files from an add-on with the same algorithm used for Volto. In the `src/customizations` folder, move any Volto customized files to `src/customizations/volto`. Then customize the add-on by reconstructing the full path (for example `@plone-collective/datatable-tutorial/CellRenderer/Progress.jsx` would be the full path for the file that customizes `datatable-tutorial/src/CellRenderer/Progress.jsx`). Can I have a theme in an add-on? : Yes, you can alias the `../../theme.config` with a `razzle.extend.js` file in the add-on root folder. Just don't make changes to the `theme.config` in the project, and don't add any files in the project's theme folder. ```jsx const modify = (config, { target, dev }, webpack) => { const themeConfigPath = `${__dirname}/theme/theme.config`; config.resolve.alias['../../theme.config$'] = themeConfigPath; config.resolve.alias['../../theme.config'] = themeConfigPath; return config; }; module.exports = { modify, }; ``` How can I avoid customizing components? : If the component is somehow configurable from Volto's configuration registry — for example, the default views, the widgets, or the route renderers — you could wrap them in another component, and replace the original component in the configuration. Or you could customize the component with the shadowing mechanism, but inside the new component reference `@plone/volto-original/.../path/to/Component`, and reuse/wrap the original one. Can I extend Volto's Express server? : You can register custom `Express` middleware. You could, for example, include a custom HTTP proxy for `ElasticSearch`, expose it to the Volto frontend and avoid security issues. See [volto-corsproxy] for a redux-integrated CORS proxy. ## Bundle optimization Once you start approaching the project delivery, you'll need to check your bundle sizes. Nobody wants to make their visitors wait for a 2 MB gzipped file before the application becomes interactive. Volto integrates a solution to split the generated JavaScript code into "chunks", which will then be loaded on-demand (when the component that uses them is loaded in the browser). When dealing with React components, it's easy: ```jsx const Select = loadable(() => import('react-select')); ``` But for libraries it's a bit more difficult. You have to manifest the library as a React component, which gets passed as a parameter to a render prop: ```jsx const D3 = loadable.lib(() => import('d3')); const FormattedValue = ({ value }) => { return ( {(d3) => d3.format(value)} ); }; ``` You can analyze your bundle by running: ```shell BUNDLE_ANALYZE=true yarn build ``` If you're running automated builds you can configure a new bundle analyzer with static output, to save the report in a static HTML file. See [webpack-bundle-analyzer] docs. To optimize this scenario Volto provides the `injectLazyLibs` HOC, which defers rendering the wrapped component until the third-party dependency is fully loaded. [volto-corsproxy]: https://github.com/eea/volto-corsproxy [webpack-bundle-analyzer]: https://github.com/webpack-contrib/webpack-bundle-analyzer