Etherpad plugin to bundle files using webpack, thus improving the performance of file loading on client-side.
Sometimes the browser takes FOREVER to load Etherpad editor, especially on instances with a lot of plugins, and with each plugin using a lot of files. On an instance with 30+ plugins and 400+ files to load, it can take up to a minute for the pad to be ready to be edited.
By installing this plugin you can speed up this process a lot:
ep_webpack
: 48s (411 requests);ep_webpack
bundling only JS files: 21s (177 requests);ep_webpack
bundling JS + CSS files: 14s (57 requests);webpack
webpack v.4
;This plugin has a watch mode, so you don't need to restart Etherpad every time you change something on the plugin files. To use it, just go the the folder where ep_webpack
is installed, and run the watch
command with the target webpack.config.*.js
file for your settings:
cd path/to/etherpad-lite/node_modules/ep_webpack && npm run watch -- --config './webpack.config-withMinifyAndCss.js'
If Docker is your thing, you can add this to your docker-compose.yml
:
webpack:
# ideally, use the same image used by Etherpad containers
image: node:8.9.0
environment:
NODE_ENV: "development"
command: bash -c "cd /etherpad-lite/node_modules/ep_webpack && npm run watch -- --config './webpack.config-withMinifyAndCss.js'"
volumes:
- path/to/etherpad-lite/:/etherpad-lite/
Here's a short explanation of what ep_webpack
does to bundle all plugins and serve a single file to the client:
loadSettings
), we get the original list of plugins & their hooks on plugins.parts
(defined on ep_etherpad-lite/static/js/pluginfw/plugins
);ep_webpack/static/js/index.js
). This allows us to use a single entry point for all dependencies;webpack
. A new file is created: ep_webpack/static/dist/js/index
;If CSS files should be bundled, some extra steps are executed on the flow mentioned above:
aceEditorCSS
hooks in order to get the list of CSS files, and we import them together with the JS single entry point (ep_webpack/static/js/index.js
);webpack
, another file is created: ep_webpack/static/dist/css/all.css
;aceEditorCSS
hooks are removed from the plugins, and the only hook of that type will point to the bundled CSS file.Sometimes an installed plugin is not ready to be used with webpack, so it is possible to ignore it when building the bundle: just include the part(s) of the plugin on your settings.json
(notice that you need to exclude the parts, not the plugins):
"ep_webpack": {
/* Ignores parts (not plugins) not ready to be bundled */
"ignoredParts": ["autocomp", "comments_page"]
}
Warning: this is an advanced customization and might not work with all the plugins
If you also want to bundle CSS files, you need to turn this feature on on the settings.json
:
"ep_webpack": {
/* Bundle CSS files too */
"bundleCSS": true
}
If you enable this feature and start to see error messages on the server console, take a look on the Troubleshooting session.
webpack
configsep_webpack
comes with a set of default configs to bundle the files, but you can override them by defining a JS object that will be used when bundling files:
"ep_webpack": {
/*
* Path to the custom webpack config file. Must be an absolute path,
* or relative to etherpad-lite/node_modules/ep_webpack/.
*/
"customWebpackConfigFile": "path/to/your/webpack.config.js"
}
The most common type of error is when trying to bundle CSS files. If you see an error message like Could not load the list of CSS files from aceEditorCSS hook, so its files won't be bundled.
, you'll need to make some changes in order to be able to bundle the CSS files:
Extract the hook into a separated file: [TL;DR:] the most effective way is to change the plugin code in order to extract the aceEditorCSS
hook into a separated JS file. See this pull request as an example.
[Long story:] Usually the error when executing the CSS hook happens because the JS file where it is defined needs to be run on the browser context, which is not where it is run when we're bundling the files. For example, the JS file might require jQuery
:
var $ = require('ep_etherpad-lite/static/js/rjquery').$;
This will certainly raise an error, as jQuery
needs window
to be defined, and it is not defined on the server side.
By putting the aceEditorCSS
hook in a separated JS file, you'll be able to require it both on client and on server sides without any issue, as this hooks only needs to return an array of strings.
Add the problematic plugin to the list of ignored parts: if you can't submit a pull request to extract aceEditorCSS
into a separated file, you can exclude the plugin from the list of bundled parts, so at least the other plugins will be able to be bundled;
Disable CSS bundling: finally, you can disable the CSS bundling entirely, which will allow you to keep bundling at least the JS files;
Want to help? Here's a list of future improvements this plugins might have:
/admin
route;jQuery
, underscore
, etc) into a separated chunk, in order to improve cache usage. From webpack
docs:
It's also good practice to extract third-party libraries, such as
lodash
orreact
, to a separatevendor
chunk as they are less likely to change than our local source code. This step will allow clients to request even less from the server to stay up to date.