Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed extension bundling from Vite to webpack #311

Merged
merged 18 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
79c7b4c
Provide more React-related imports for new jsx-runtime and other need…
tjcouch-sil Jul 14, 2023
dfe3237
Added @sillsdev/scripture to packages we provide
tjcouch-sil Jul 15, 2023
73197d8
Hopefully sped up erb eslint
tjcouch-sil Jul 19, 2023
d93392b
Changed extensions lib to src
tjcouch-sil Jul 19, 2023
0eb68bd
Converted extensions from vite to webpack
tjcouch-sil Jul 20, 2023
c928949
Updated dependencies
tjcouch-sil Jul 24, 2023
a4e4520
Zip extensions into release folder
tjcouch-sil Jul 20, 2023
e84d769
Stopped running evil extension through webpack since it was messing u…
tjcouch-sil Jul 21, 2023
68f2773
Fixed web-views not working other than in root of extension
tjcouch-sil Jul 21, 2023
ea23116
Added second Hello World React webview, moved webviews into web-views…
tjcouch-sil Jul 21, 2023
323509a
Added helloWorld.onHelloWorld event for all three hello world webview…
tjcouch-sil Jul 21, 2023
c936ce9
Added logLevel command-line arg, fixed importing production webpack e…
tjcouch-sil Jul 21, 2023
4b44ca5
Fixed extensions sometimes not loading in production because of weird…
tjcouch-sil Jul 24, 2023
23356ee
Fixed jest importing tsconfig which is not normal json
tjcouch-sil Jul 24, 2023
2cf8372
Switched to commonjs-static modules for more predictable use, other c…
tjcouch-sil Jul 25, 2023
b3d7877
Set request timeout to 10 seconds in dev, quick fix for ref-selector bug
tjcouch-sil Jul 25, 2023
3d0dd78
Changed extension dependencies to peerDependencies since the only ing…
tjcouch-sil Jul 26, 2023
cbe8dff
Clarified when evil console logs are actual problems
tjcouch-sil Jul 26, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .erb/configs/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"no-console": "off",
"global-require": "off",
"import/no-dynamic-require": "off"
}
},
"ignorePatterns": ["node_modules"]
}
3 changes: 2 additions & 1 deletion extensions/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ node_modules

# Built files
dist
temp-vite
release
temp-build
3 changes: 2 additions & 1 deletion extensions/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ module.exports = {
'import/resolver': {
// See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below
node: {},
// Disable webpack eslint import resolver since we are using vite
// Disable webpack eslint import resolver from parent since we are in a different directory
// TODO: make an eslint webpack resolver for this extensions folder
webpack: { config: { resolve: { extensions: [] } } },
typescript: {
alwaysTryTypes: true,
Expand Down
5 changes: 3 additions & 2 deletions extensions/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ lerna-debug.log*

node_modules
dist
release
dist-ssr
*.local

Expand All @@ -21,5 +22,5 @@ dist-ssr
*.sln
*.sw?

# Vite-built temp WebView files
temp-vite
# Temporary intermediate build files
temp-build
20 changes: 18 additions & 2 deletions extensions/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,31 @@
"request": "launch",
"runtimeExecutable": "npm",
"skipFiles": ["<node_internals>/**"],
"runtimeArgs": ["run", "start:vite"]
"runtimeArgs": ["run", "watch"]
},
{
"name": "Build WebViews",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"skipFiles": ["<node_internals>/**"],
"runtimeArgs": ["run", "build:web-view"]
},
{
"name": "Build Main",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"skipFiles": ["<node_internals>/**"],
"runtimeArgs": ["run", "build:main"]
},
{
"name": "Build Extensions",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"skipFiles": ["<node_internals>/**"],
"runtimeArgs": ["run", "build:vite"]
"runtimeArgs": ["run", "build"]
},
{
"name": "Debug Paranext Core",
Expand Down
55 changes: 19 additions & 36 deletions extensions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@ Official extensions provided by Paranext

## Summary

This is a Vite project configured to build Paranext's official extensions included in the product.
This is a webpack project configured to build Paranext's official extensions included in the product.

- `lib` contains the source code for each extension
- Each sub-folder in `lib` with a `manifest.json` in it is an extension
- `src` contains the source code for each extension
- Each sub-folder in `src` with a `manifest.json` in it is an extension
- The main entry file is likely named the same as the extension name
- `manifest.json` is the manifest file that defines the extension
- `package.json` defines the npm package for this extension and is required for Paranext to use it appropriately
- `<extension_name>.d.ts` is this extension's types file that other extensions can use
- `*.web-view.tsx` files are React WebViews
- `*.web-view.ejs` files are HTML WebViews
- `dist` is a generated folder containing your built extension files
- `manifest.json` is the manifest file that defines the extension and important properties for Paranext
- `package.json` contains information about this extension npm package. It is required for Paranext to use the extension properly. It is copied into the build folder
- `<extension_name>.d.ts` is this extension's types file that defines how other extensions can use this extension through the `papi`
- `*.web-view.tsx` files will be treated as React WebViews
- `*.web-view.html` files are a conventional way to provide HTML WebViews (no special functionality)
- `assets` contains asset files the extension and its WebViews can retrieve using the `papi-extension:` protocol
- `dist` is a generated folder containing the built extension files
- `release` is a generated folder containing zips of the built extension files

## To install

Expand All @@ -35,39 +37,20 @@ Note: The extensions will be the `dist` folder. These extension files will be wa

### Building your extension independently

To watch extension files (in `lib`) for changes:
To watch extension files (in `src`) for changes:

`npm start:vite`
`npm run watch`

To build the extensions once:

`npm run build:vite` or `npm run build`
`npm run build`

## Vite Build Explanation
## To package for distribution

These extensions are built by Vite in two steps: a WebView transpilation step and a packaging step:
To package your extension into a zip file for distribution:

## Build 1: TypeScript WebView transpilation
`npm run package`

Vite prepares TypeScript WebViews for use and outputs them into `temp-vite` folders adjacent to the WebView files:
## Special features of this project

- Formats WebViews to match how they should look to work in Paranext
- Transpiles React/TypeScript WebViews into JavaScript
- Packages dependencies into the WebViews
- Embeds Sourcemaps into the WebViews inline

## Built 2: Packaging

Vite packages the extensions together into the `dist` folder:

- Transpiles each main TypeScript file and its imported modules into JavaScript
- Injects the WebViews into the main files
- Packages dependencies into the main files
- Generates sourcemaps for the files
- Packages everything up into each extension folder in `dist`

Note: When performing the second build step, the following line may occur in your console. Please feel free to ignore it as it is a false positive. It is likely showing because WebViews are embedded in the entry file:

```bash
transforming (1) lib\main.ts[plugin:ImportManager] It seems like there are multiple imports of module 'react'. You should examine that.
```
This project has special features and specific configuration to make building extensions for Paranext easier. See [Special features of `paranext-extension-template`](https://github.com/paranext/paranext-extension-template#special-features-of-the-template) for information on these special features.
8 changes: 0 additions & 8 deletions extensions/lib/hello-world/hello-world.d.ts

This file was deleted.

1 change: 0 additions & 1 deletion extensions/lib/vite-env.d.ts

This file was deleted.

41 changes: 41 additions & 0 deletions extensions/lib/zip-extensions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* eslint-disable no-console */

import path from 'path';
import fs from 'fs';
import zipFolder from 'zip-folder-promise';
import { getExtensions, outputFolder } from '../webpack/webpack.util';
import { rootDir } from '../webpack/webpack.config.base';

/** Folder for where the zipped files should be placed */
const releaseFolder = path.join(rootDir, 'release');

/** Creates a zip for each extension and puts them in the release folder */
async function zipExtensions() {
// Get all the extensions (this is technically based on source files, not on the output files)
// TODO: make this based on output files
const extensions = await getExtensions();

// Delete the release folder if it exists
await fs.promises.rm(releaseFolder, { recursive: true, force: true });
// Create the release folder as zipFolder doesn't work unless that folder exists
await fs.promises.mkdir(releaseFolder, { recursive: true });

const zipPromises = extensions.map(async (extension) => {
try {
/** Directory to zip. The output extension folder */
const dirToZip = path.join(rootDir, outputFolder, extension.dirName);
/** The file to output. Into release folder. `<extension_directory_name>_<extension_manifest_version>.zip */
const outputFile = path.join(releaseFolder, `${extension.dirName}_${extension.version}.zip`);

return zipFolder(dirToZip, outputFile);
} catch (e) {
const error = `Error on zipping ${extension.dirName}: ${e}`;
console.error(error);
throw new Error(error);
}
});

return Promise.all(zipPromises);
}

zipExtensions();
Loading
Loading