Skip to content

Commit

Permalink
Add libraryFile configuration option (#755)
Browse files Browse the repository at this point in the history
* Add libraryFile config option.

* Add test for libraryFile config option.

* Add changeset.

* Update changeset with PR feedback

Co-authored-by: Adam Skoufis <askoufis@users.noreply.github.com>

* Remove unnecessary @ts-ignore directive from library fixtures.

* Update libraries documentation to use TypeScript for config examples.

* Update SKU_LIBRARY_* global variable names to match other globals.

---------

Co-authored-by: Adam Skoufis <askoufis@users.noreply.github.com>
  • Loading branch information
kjots and askoufis committed Mar 30, 2023
1 parent 4255556 commit 40022c8
Show file tree
Hide file tree
Showing 28 changed files with 296 additions and 12 deletions.
24 changes: 24 additions & 0 deletions .changeset/many-toys-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
'sku': minor
---

Add `libraryFile` configuration option

This option allows the file name of the library to be specified in the sku configuration.
If this option is not specified then the `libraryName` option will be used for this purpose instead (note that this is the previously existing behaviour).

**EXAMPLE USAGE**:

```typescript
// sku.config.ts
import type { SkuConfig } from 'sku';

const skuConfig: SkuConfig = {
libraryEntry: 'src/library.js',
renderEntry: 'src/render.js',
libraryName: 'MyAwesomeLibrary',
libraryFile: 'my-awesome-library',
};

export default skuConfig;
```
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"__SKU_DEV_HTTPS__": true,
"__SKU_DEV_MIDDLEWARE_ENABLED__": true,
"__SKU_DEV_MIDDLEWARE_PATH__": true,
"SKU_LIBRARY_NAME": true
"__SKU_LIBRARY_NAME__": true,
"__SKU_LIBRARY_FILE__": true
}
}
11 changes: 11 additions & 0 deletions docs/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,17 @@ type `string`

The global name of the library. Will be added to the `window` object under `window[libraryName]`.

## libraryFile

type `string`

**Only for libraries**

The file name of the library. The main bundle of the library will be output to `dist/${libraryFile}.js` - note that the
`.js` extension will be added automatically and should not be included in the configuration option itself.

If `libraryFile` is not specified then `libraryName` will be used instead.

## persistentCache

type `boolean`
Expand Down
21 changes: 19 additions & 2 deletions docs/docs/libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,31 @@ If you need to build a UMD library instead of a web site, you can provide a `lib

> If you are creating a package to share between multiple sku apps, then you probably want [compile packages](./docs/extra-features#compile-packages) instead. Libraries should only be used when you have very little control over the target environment (e.g. legacy applications, externally hosted solutions like Auth0).
```js
modules.exports = {
```typescript
// sku.config.ts
import type { SkuConfig } from 'sku';

const skuConfig: SkuConfig = {
libraryEntry: 'src/library.js',
renderEntry: 'src/render.js',
libraryName: 'MyAwesomeLibrary',
};

export default skuConfig;
```

By default the file name of the library will be based on the `libraryName` option. A distinct library file name may be specified by providing a `libraryFile` option:

```typescript
const skuConfig: SkuConfig = {
//
libraryName: 'MyAwesomeLibrary',
libraryFile: 'my-awesome-library',
};
```

Note that `libraryFile` should _not_ include a `.js` extension as this will be added to the library file name automatically.

Your `library` entry must export its public API via a default export:

```js
Expand Down
1 change: 0 additions & 1 deletion fixtures/library-build/src/styles.treat.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-ignore
import { style } from 'sku/treat';

export const customBox = style({
Expand Down
7 changes: 7 additions & 0 deletions fixtures/library-file/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# managed by sku
*.less.d.ts
coverage/
dist-storybook/
dist/
report/
# end managed by sku
9 changes: 9 additions & 0 deletions fixtures/library-file/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# managed by sku
.eslintrc
.prettierrc
coverage/
dist-storybook/
dist/
report/
tsconfig.json
# end managed by sku
7 changes: 7 additions & 0 deletions fixtures/library-file/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# managed by sku
*.less.d.ts
coverage/
dist-storybook/
dist/
report/
# end managed by sku
8 changes: 8 additions & 0 deletions fixtures/library-file/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@sku-fixtures/library-file",
"private": true,
"dependencies": {
"dedent": "^0.7.0",
"sku": "workspace:*"
}
}
8 changes: 8 additions & 0 deletions fixtures/library-file/sku.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
libraryEntry: 'src/library.js',
renderEntry: 'src/render.js',
libraryName: 'MyLibrary',
libraryFile: 'my-library',
port: 8086,
persistentCache: false,
};
1 change: 1 addition & 0 deletions fixtures/library-file/src/dynamicImports/unused.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const message = 'UNUSED';
1 change: 1 addition & 0 deletions fixtures/library-file/src/dynamicImports/used.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const message = 'This element was generated by the library';
12 changes: 12 additions & 0 deletions fixtures/library-file/src/library.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import styles from './styles.less';
import { customBox } from './styles.treat';

export default () => {
const dynamicImport = 'used';
import(`./dynamicImports/${dynamicImport}`).then(({ message }) => {
const el = document.createElement('div');
el.className = `${styles.root} ${customBox}`;
el.innerHTML = message;
document.body.appendChild(el);
});
};
19 changes: 19 additions & 0 deletions fixtures/library-file/src/render.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import dedent from 'dedent';

export default {
renderDocument: ({ libraryName, headTags, bodyTags }) => dedent`
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My Awesome Project</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
${headTags}
</head>
<body>
${bodyTags}
<script>window.${libraryName}();</script>
</body>
</html>
`,
};
3 changes: 3 additions & 0 deletions fixtures/library-file/src/styles.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.root {
color: red;
}
7 changes: 7 additions & 0 deletions fixtures/library-file/src/styles.less.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
'root': string;
}
export const cssExports: CssExports;
export default cssExports;
8 changes: 8 additions & 0 deletions fixtures/library-file/src/styles.treat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { style } from 'sku/treat';

export const customBox = style({
backgroundColor: 'lightseagreen',
color: 'white',
fontSize: 50,
padding: 20,
});
6 changes: 4 additions & 2 deletions packages/sku/config/webpack/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const {
polyfills,
isLibrary,
libraryName,
libraryFile,
supportedBrowsers,
displayNamesProd,
cspEnabled,
Expand Down Expand Up @@ -99,7 +100,7 @@ const makeWebpackConfig = ({
// Libraries should always have the same file name
// for the main chunk unless we're building for storybook
if (isLibrary && isMainChunk) {
return libraryName;
return libraryFile ?? libraryName;
}

// The client file mask is set to just name in start/dev mode as contenthash
Expand Down Expand Up @@ -314,7 +315,8 @@ const makeWebpackConfig = ({
...(htmlRenderPlugin ? [htmlRenderPlugin.rendererPlugin] : []),
new webpack.DefinePlugin(envVars),
new webpack.DefinePlugin({
SKU_LIBRARY_NAME: JSON.stringify(libraryName),
__SKU_LIBRARY_NAME__: JSON.stringify(libraryName),
__SKU_LIBRARY_FILE__: JSON.stringify(libraryFile),
__SKU_PUBLIC_PATH__: JSON.stringify(paths.publicPath),
__SKU_CSP__: JSON.stringify({
enabled: cspEnabled,
Expand Down
4 changes: 4 additions & 0 deletions packages/sku/context/configSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ module.exports = validator.compile({
type: 'string',
optional: true,
},
libraryFile: {
type: 'string',
optional: true,
},
dangerouslySetWebpackConfig: {
type: 'function',
},
Expand Down
1 change: 1 addition & 0 deletions packages/sku/context/defaultSkuConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module.exports = {
publicPath: '/',
polyfills: [],
libraryName: null,
libraryFile: null,
sourceMapsProd: false,
displayNamesProd: false,
dangerouslySetWebpackConfig: defaultDecorator,
Expand Down
1 change: 1 addition & 0 deletions packages/sku/context/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ module.exports = {
server: skuConfig.serverPort,
},
libraryName: skuConfig.libraryName,
libraryFile: skuConfig.libraryFile,
isLibrary: Boolean(skuConfig.libraryEntry),
storybookPort: skuConfig.storybookPort,
storybookTarget: skuConfig.storybookTarget,
Expand Down
11 changes: 7 additions & 4 deletions packages/sku/entry/libraryRender/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import render from '__sku_alias__renderEntry';

const libraryName = SKU_LIBRARY_NAME;
const libraryName = __SKU_LIBRARY_NAME__;
const libraryFile = __SKU_LIBRARY_FILE__;
const publicPath = __SKU_PUBLIC_PATH__;

const libraryPath = `${publicPath}${libraryFile ?? libraryName}`;

export default (renderParams) => {
const renderContext = { ...renderParams, libraryName };
const renderContext = { ...renderParams, libraryName, libraryFile };

return render.renderDocument({
...renderContext,
headTags: `<link rel="stylesheet" type="text/css" href="${publicPath}${libraryName}.css">`,
bodyTags: `<script src="${publicPath}${libraryName}.js"></script>`,
headTags: `<link rel="stylesheet" type="text/css" href="${libraryPath}.css">`,
bodyTags: `<script src="${libraryPath}.js"></script>`,
});
};
5 changes: 3 additions & 2 deletions packages/sku/entry/render/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import createCSPHandler from '../csp';

import render from '__sku_alias__renderEntry';

const libraryName = SKU_LIBRARY_NAME;
const libraryName = __SKU_LIBRARY_NAME__;
const libraryFile = __SKU_LIBRARY_FILE__;
const publicPath = __SKU_PUBLIC_PATH__;
const csp = __SKU_CSP__;

Expand All @@ -18,7 +19,7 @@ export const serializeConfig = (config) =>
)}</script>`;

export default async (renderParams) => {
const renderContext = { ...renderParams, libraryName };
const renderContext = { ...renderParams, libraryName, libraryFile };

let app;
let clientContext = {};
Expand Down
13 changes: 13 additions & 0 deletions packages/sku/sku-types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface SharedRenderProps {
site: string;
language: string;
libraryName: string;
libraryFile: string;
// Webpack use an any here. PR for better type welcome.
webpackStats: any;
}
Expand Down Expand Up @@ -212,6 +213,18 @@ export interface SkuConfig {
*/
libraryName?: string;

/**
* **Only for libraries**
*
* The file name of the library. The main bundle of the library will be output to `dist/${libraryFile}.js` - note that the
* `.js` extension will be added automatically and should not be included in the configuration option itself.
*
* If `libraryFile` is not specified then `libraryName` will be used instead.
*
* @link https://seek-oss.github.io/sku/#/./docs/configuration?id=libraryfile
*/
libraryFile?: string;

/**
* Enables linting of import order. This rule supports auto-fix.
*
Expand Down
10 changes: 10 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 40022c8

Please sign in to comment.