Skip to content

Commit

Permalink
Merge pull request #60 from jwanner83/#9-add-watch-mode-with-hmr
Browse files Browse the repository at this point in the history
#9 add watch mode with hmr
  • Loading branch information
jwanner83 authored Jan 8, 2024
2 parents 58898ca + 701ab4c commit 9fda8ab
Show file tree
Hide file tree
Showing 61 changed files with 4,850 additions and 4,127 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
**/dist
**/build
.pnpm-debug.log
**/.env
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022 Jonas Wanner
Copyright (c) 2024 Jonas Wanner

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
124 changes: 57 additions & 67 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,100 +1,90 @@
# liferay-npm-bundler-improved

A non-official but **ultrafast** drop-in replacement for the
[`liferay-npm-bundler` \*](https://www.npmjs.com/package/liferay-npm-bundler)
`liferay-npm-bundler-improved` is a **high-speed**, unofficial drop-in replacement for
the [`liferay-npm-bundler`](https://www.npmjs.com/package/liferay-npm-bundler) with added watch mode functionality.

## advantages
## description

the two main advantages are _**speed**_ and _**traceability**_.
`liferay-npm-bundler-improved` is a bundler for liferay portlets that consolidates all dependencies into a single file.
Additionally, it copies assets into the `build` folder and provides access to them through the web context URL. The tool
also offers a watch mode that rebuilds the portlet upon file changes.

### speed
## getting started

a build of an average portlet with the `liferay-npm-bundler-improved` takes about **_0.1s_** \*\*, no matter how big the
module is. if you worked with the official `liferay-npm-bundler` before, you know how much of an improvement this is.
### installation

### traceability
To install, run the following command:

the `liferay-npm-bundler-improved` tries its best to tell you, if you do something wrong. this helps the developer a
lot if he is trying to figure out why something isn't working as expected. some examples.
```bash
pnpm i --D liferay-npm-bundler-improved
```

#### missing key in `package.json`
### existing portlet

if you forgot a required key in the `package.json`, it tells you which key you're missing and lets the build fail.
for example, if you forgot the `name` key, the console output would look something like this:
To use `liferay-npm-bundler-improved` in an existing portlet, replace instances of `liferay-npm-bundler`
with `liferay-npm-bundler-improved` in your build command.

```
Error in 0.01s: bundler failed. invalid-package-exception: required property "name" doesn't exist in the package.json file.
```
#### copy sources

#### missing entry file
If your build command includes `lnbs-copy-sources`, remove it and add `--copy-sources` to
the `liferay-npm-bundler-improved` command.

if, for some reason, the in the `main` property defined entry js file is missing, the bundler will show the following
output. _(the original bundler wouldn't even fail if the entry file was not found. it would just tell you that its
finished.)_
#### copy assets

with the `--copy-sources` option activated:
For assets located in the `assets` folder that need to be available through the web context URL, remove
the `lnbs-copy-assets` command from your existing build command and add `--copy-assets` to
the `liferay-npm-bundler-improved` call.

```
Error in 0.01s: bundler failed. copy-sources-exception: sources could not be copied from "src/entry.js"
```
### new portlet

without:
Refer to the examples folder for guidance on using `liferay-npm-bundler-improved` in a `react`, `vue`, or plain `js`
portlet.

```
Error in 0.01s: bundler failed. missing-entry-file-exception: entry file doesn't exist in "build/entry.js". if there is no build step and you need the source entry file, you may want to enable the copy sources option: '--copy-sources'
```
## advantages

#### missing css file if `header-portlet-css` is enabled
The main advantages of using `liferay-npm-bundler-improved` are enhanced **speed** and a better **developer experience
**.

if the `header-portlet-css` option is active and the defined css file can't be found, the bundler doesn't fail but shows
a warning after the build is done.
### speed

```
Success in 0.04s: bundler done with one warning
↳ the 'com.liferay.portlet.header-portlet-css' property is set but the according css file can't either be found in 'src/index.css' or in 'build/index.css'. please make sure, the css file is present in one of the directories or remove the property.
```
The build time for an average portlet with `liferay-npm-bundler-improved` is approximately **0.1s**, regardless of
module size. This represents a significant improvement over the official `liferay-npm-bundler`.

## missing features
### developer experience

the current implementation works for most use cases. but there are a few things which aren't currently working as the
original implementation.
`liferay-npm-bundler-improved` offers detailed error reporting, aiding developers in identifying and resolving issues.
Examples include identifying missing keys in `package.json` and detecting missing entry files.

- package deduplication - _not planned \*\*\*_
- system configuration - [gathering interest](https://github.com/jwanner83/liferay-npm-bundler-improved/issues/55) \
↳ portlet instance configuration works since 1.4.0 [#8](https://github.com/jwanner83/liferay-npm-bundler-improved/issues/8)
### deploy mode

## usage
When the `--deploy` option or `-d` is set, the bundler deploys the portlet to the server after the build, using the path
specified in the `.env` file under `LIFERAY_DEPLOYMENT_PATH`.

To use the bundler, you have to install it from the `npmjs.org` registry `pnpm i --D liferay-npm-bundler-improved`
and edit your existing build command to use `liferay-npm-bundler-improved` instead of `liferay-npm-bundler`. most of the
features will work out of the box.
### watch mode

### copy sources
`liferay-npm-bundler-improved` supports a watch mode, allowing automatic portlet rebuilds upon file changes. This is
invaluable for immediate feedback during portlet development. Include the `--watch` option or `-w` in the build command
to enable watch mode. (It is possible to use the `--deploy` option in conjunction with the `--watch` option.)

if you have `lnbs-copy-sources` inside of your build command, remove it and add `--copy-sources` to the
`liferay-npm-bundler-improved` command.
> [!IMPORTANT]
> The watch mode currently works exclusively with vite as the build tool. It is highly efficient for smaller bundles but
> may not be as effective for larger ones (taking more than 10 seconds to complete).
### copy assets
## missing features

if you have assets inside the `assets` folder which should be available through the web context url, remove the
`lnbs-copy-assets` command from your existing build command and add `--copy-assets` to the
`liferay-npm-bundler-improved` call
While the current implementation is suitable for most use cases, there are a few features from the original
implementation that are not yet supported:

### configuration
portlet instance configuration will work the same way as in the official bundler. see the `examples/plain/features/configuration.json`
file for all available options. it is also possible to add translated labels, descriptions and default values with
language keys. the keys have to be defined inside the portlets own localization files.
- Package deduplication (not planned for implementation)
- System configuration - Gathering interest for
implementation ([link](https://github.com/jwanner83/liferay-npm-bundler-improved/issues/55))

### examples
<br>

see the examples folder for an example on how to use the `liferay-npm-bundler-improved` in a `react`, `vue` and plain `js`
portlet.
_\* The official bundler
is [available on GitHub](https://github.com/liferay/liferay-frontend-projects/tree/master/projects/js-toolkit/packages/npm-bundler)_

\
_\* the official bundler is
[available on github](https://github.com/liferay/liferay-frontend-projects/tree/master/projects/js-toolkit/packages/npm-bundler)_
<br>
_\*\* on a apple m1 macbook pro. on windows it takes about 0.3s._<br>
_\*\*\* the package deduplication feature is currently not planned because of the cost/income ratio. if this feature would be
implemented, the speed of the bundler would decrease a lot and because we didn't use this feature anyway in the company
i worked, i left it out._
_\*\* Timings are based on an Apple M1 MacBook Pro. On Windows, the timing is approximately 0.3s._

_\*\*\* The package deduplication feature is not planned due to its potential impact on bundler speed and the perceived
low usage in practice._
1 change: 0 additions & 1 deletion bundler/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
bin
build
dist
../node_modules
.pnpm-debug.log
Expand Down
21 changes: 18 additions & 3 deletions bundler/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "liferay-npm-bundler-improved",
"description": "A non-official but ultrafast drop-in replacement for the liferay-npm-bundler",
"version": "1.4.0",
"version": "1.5.0-beta.11",
"author": "Jonas Wanner",
"license": "ISC",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/jwanner83/liferay-npm-bundler-improved"
Expand All @@ -26,10 +26,20 @@
},
"dependencies": {
"@types/archiver": "^5.1.1",
"ansi-to-html": "^0.7.2",
"archiver": "^5.3.0",
"arg": "^5.0.1",
"chalk": "^4.1.2",
"regenerator-runtime": "^0.13.9"
"cheerio": "1.0.0-rc.12",
"chokidar": "^3.5.3",
"connect": "^3.7.0",
"dayjs": "^1.11.7",
"dotenv": "^16.0.3",
"harmon": "^1.4.4",
"http-proxy": "^1.18.1",
"regenerator-runtime": "^0.13.9",
"vite": "^3.0.4",
"ws": "^8.13.0"
},
"devDependencies": {
"@babel/core": "^7.17.9",
Expand All @@ -38,6 +48,9 @@
"@rollup/plugin-commonjs": "^19.0.0",
"@rollup/plugin-eslint": "^8.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"@types/react": "^17.0.11",
"@types/react-dom": "^17.0.7",
"@typescript-eslint/eslint-plugin": "^4.31.2",
"@typescript-eslint/parser": "4.0.0",
"esbuild": "^0.12.28",
Expand All @@ -47,6 +60,8 @@
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"readline": "^1.3.0",
"regenerator-runtime": "^0.13.9",
"rollup": "^2.60.2",
Expand Down
115 changes: 74 additions & 41 deletions bundler/rollup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,84 @@ import { getBabelOutputPlugin } from '@rollup/plugin-babel'
import commonjs from '@rollup/plugin-commonjs'
import eslint from '@rollup/plugin-eslint'
import json from '@rollup/plugin-json'
import { RollupOptions } from 'rollup'
import copy from 'rollup-plugin-copy'
import esbuild from 'rollup-plugin-esbuild'
import resolve from '@rollup/plugin-node-resolve'
import { preserveShebangs } from 'rollup-plugin-preserve-shebangs'
import { Plugin, RollupOptions } from 'rollup'
import replace from '@rollup/plugin-replace'

const config: RollupOptions = {
input: 'src/mod.ts',
plugins: [
preserveShebangs(),
eslint(),
commonjs(),
json(),
esbuild({
minify: true
}),
copy({
targets: [
{
src: 'src/templates/*',
dest: 'dist/templates/'
}
]
}),
getBabelOutputPlugin({
presets: ['@babel/preset-env']
})
],
output: [
{
file: 'bin/bundler.js',
format: 'cjs',
compact: true,
banner: '#!/usr/bin/env node'
const config: RollupOptions[] = [
{
input: 'src/templates/dev/mod.tsx',
plugins: [
resolve(),
json(),
commonjs(),
esbuild(),
replace({
preventAssignment: true,
'process.env.NODE_ENV': JSON.stringify('production')
})
],
output: {
file: 'dist/templates/dev.js',
format: 'commonjs',
exports: 'default'
}
],
external: [
'fs',
'util',
'regenerator-runtime/runtime',
'path',
'archiver',
'chalk',
'readline',
'arg'
]
}
},
{
input: 'src/mod.ts',
plugins: [
preserveShebangs(),
eslint(),
commonjs({
transformMixedEsModules: true
}),
json(),
esbuild({
minify: true
}),
copy({
targets: [
{
src: 'src/templates/plain/*',
dest: 'dist/templates/'
}
]
}) as Plugin,
getBabelOutputPlugin({
presets: ['@babel/preset-env']
})
],
output: [
{
file: 'bin/bundler.js',
format: 'cjs',
compact: true,
banner: '#!/usr/bin/env node'
}
],
external: [
'fs',
'util',
'regenerator-runtime/runtime',
'path',
'archiver',
'chalk',
'readline',
'arg',
'vite',
'connect',
'http-proxy',
'http',
'harmon',
'ws',
'chokidar',
'dotenv',
'dayjs'
]
}
]

export default config
Loading

0 comments on commit 9fda8ab

Please sign in to comment.