Skip to content

Commit

Permalink
🏗️build (browser): add a browserify-based browser build, complete wit…
Browse files Browse the repository at this point in the history
…h polyfills.
  • Loading branch information
mathe42 authored and jjhbw committed Aug 6, 2021
1 parent 7eda590 commit 3d6c1a8
Show file tree
Hide file tree
Showing 9 changed files with 404 additions and 15 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,7 @@ rules:
no-extra-bind: error
linebreak-style:
- error
- unix
- unix
ignorePatterns:
- "src/browser-polyfill.ts"
- "src/browser.ts"
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ coverage
/examples
/.github
/lib/__tests__
/rollup.config.js
/.prettierrc
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,15 @@ Check out the [Node examples folder](https://github.com/guigrpa/docx-templates/t

# Browser usage

You can use docx-templates in the browser (yay!). Just as when using docx-templates in Node, you need to provide the template contents as a buffer-like object. For example, you can get a `File` object with:
You can use docx-templates in the browser (yay!). Just as when using docx-templates in Node, you need to provide the template contents as a `Buffer`-like object.

For example when the template is on your server you can get it with something like:

```js
const template = await fetch('./template.docx').then(res => res.arrayBuffer())
```

Or if the user provides the template you can get a `File` object with:

```html
<input type="file">
Expand Down Expand Up @@ -149,10 +157,21 @@ const readFileIntoArrayBuffer = fd =>

You can find an example implementation of `saveDataToFile()` [in the Webpack example](https://github.com/guigrpa/docx-templates/blob/79119723ff1c009b5bbdd28016558da9b405742f/examples/example-webpack/client/index.js#L82).

Check out the examples [using Webpack](https://github.com/guigrpa/docx-templates/tree/master/examples/example-webpack) and [using Browserify](https://github.com/guigrpa/docx-templates/tree/master/examples/example-browserify).
Check out the examples [using Webpack](https://github.com/guigrpa/docx-templates/tree/master/examples/example-webpack) and [using Browserify](https://github.com/guigrpa/docx-templates/tree/master/examples/example-browserify) or you can use the browserified bundle directly as discussed below.

## Polyfilled browser-ready bundle
As this library depends on the internal NodeJS modules `vm`, `stream`, `util`, `events` and the `Buffer` global, your build tools have to polyfill these modules when using the library in the browser. We provide a browser build wich includes the required polyfills. Its file size is about 300K uncompressed or 85K / 70K with gzip / brotli compression).

You can import the library directly **as a module** using e.g. the unpkg.com CDN, like below, or you can host the `/lib/browser.js` bundle yourself.

```ts
import createReport from 'https://unpkg.com/docx-templates/lib/browser.js';
```

this is good for testing or prototyping but you should keep in mind that the `browser.js` is `es2017` code wich is supported by only 95% of users. If you have to support IE or old browser versions, you are better off compiling it to your target. Also see the support table for `es2017` [here](https://caniuse.com/sr_es8).

## Browser compatibility caveat
Note that the JavaScript code in your docx template will be run as-is by the browser. Transpilers like Babel can't see this code, and won't be able to polyfill it. This means that the JS code in your template needs to be compatible with the browsers you are targeting. In other words: don't use fancy modern syntax and functions in your template if you want older browsers, like IE11, to be able to render it.
## Browser template compatibility caveat
Note that the JavaScript code in your .docx template will be run as-is by the browser. Transpilers like Babel can't see this code, and won't be able to polyfill it. This means that the JS code in your template needs to be compatible with the browsers you are targeting. In other words: don't use fancy modern syntax and functions in your template if you want older browsers, like IE11, to be able to render it.

# Writing templates

Expand Down
18 changes: 15 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"url": "git+https://github.com/guigrpa/docx-templates.git"
},
"scripts": {
"compile": "rimraf ./lib && tsc",
"compile": "rimraf ./lib && yarn rollup && tsc",
"rollup": "rollup -c",
"prepack": "yarn compile",
"travis": "yarn compile && yarn test",
"jest": "jest --watch --coverage",
Expand All @@ -36,34 +37,45 @@
"lint-fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\""
},
"engines": {
"node": ">=6"
"node": ">=8.1"
},
"dependencies": {
"jszip": "^3.5.0",
"sax": "1.2.4",
"timm": "^1.6.2"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^20.0.0",
"@rollup/plugin-node-resolve": "^13.0.4",
"@rollup/plugin-replace": "^3.0.0",
"@types/jest": "^26.0.0",
"@types/node": "^15.9.0",
"@types/qrcode": "^1.3.4",
"@types/sax": "^1.2.1",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"buffer": "^6.0.3",
"coveralls": "^3.0.13",
"esbuild": "^0.12.18",
"eslint": "^7.3.1",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-jest": "^24.0.1",
"eslint-plugin-prettier": "^3.1.2",
"events": "^3.3.0",
"jest": "^27.0.4",
"mockdate": "^3.0.2",
"nyc": "^15.0.1",
"prettier": "^2.0.5",
"qrcode": "^1.4.4",
"rimraf": "^3.0.2",
"rollup": "^2.56.0",
"rollup-plugin-esbuild": "^4.5.0",
"stream-browserify": "^3.0.0",
"ts-jest": "^27.0.2",
"typescript": "^4.2.3"
"typescript": "^4.2.3",
"util": "^0.12.4",
"vm-browserify": "^1.1.2"
},
"jest": {
"transform": {
Expand Down
46 changes: 46 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import replace from '@rollup/plugin-replace'
import esbuild from 'rollup-plugin-esbuild'
import node from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'


export default {
input: './src/browser.ts',
output: { file: './lib/browser.js', format: 'es', exports: 'named', sourcemap: true },
plugins: [
node({
preferBuiltins: false
}),
commonjs(),
// Set some node specific globals
replace({
values: {
'process.env.NODE_DEBUG': false,
'process.pid': 42,
'process.nextTick': 'setTimeout',
'process.stdout': 'null',
'process.stderr': 'null',
'process.env.READABLE_STREAM': 'false',
'process.browser': 'true',
'process.env.NODE_ENV': '"production"',
'process': 'undefined'
}
}),
esbuild({
target: 'es2017',
minify: true
}),
// Map modules to polyfill
{
name: 'module-map',
resolveId(id) {
if (id === 'vm') {
return this.resolve('vm-browserify')
}
if (id === 'stream') {
return this.resolve('stream-browserify')
}
}
}
]
}
4 changes: 4 additions & 0 deletions src/browser-polyfill.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { Buffer } from 'buffer/';

(<any>globalThis).Buffer = Buffer;
2 changes: 2 additions & 0 deletions src/browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import './browser-polyfill';
export * from './index';
4 changes: 4 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@
},
"include": [
"src"
],
"exclude": [
"src/browser-polyfill.ts",
"src/browser.ts",
]
}
Loading

0 comments on commit 3d6c1a8

Please sign in to comment.