Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/big-walls-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'preact-cli': patch
---

Added typings for users to use in their preact.config.js files
10 changes: 9 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,13 @@
"react/jsx-no-undef": 2,
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2
}
},
"overrides": [
{
"files": ["**/*.ts"],
"rules": {
"no-undef": "off"
}
}
]
}
40 changes: 11 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,35 +219,17 @@ To customize preact-cli create a `preact.config.js` or a `preact.config.json` fi
```js
// ... imports or other code up here ...

// these props are both optional
export default {
// you can add preact-cli plugins here
plugins: [
// either a function
// (you'd probably import this because you can use the `webpack` function instead of an inline plugin)
function () {},
// strings also work (they get imported by preact-cli), useful for the json config
'plugin-name',
// with options
[
'plugin-name',
{
option: true,
},
],
],
/**
* Function that mutates the original webpack config.
* Supports asynchronous changes when a promise is returned (or it's an async function).
*
* @param {object} config - original webpack config.
* @param {object} env - options passed to the CLI.
* @param {WebpackConfigHelpers} helpers - object with useful helpers for working with the webpack config.
* @param {object} options - this is mainly relevant for plugins (will always be empty in the config), default to an empty object
**/
webpack(config, env, helpers, options) {
/** you can change the config here **/
},
/**
* Function that mutates the original webpack config.
* Supports asynchronous changes when a promise is returned (or it's an async function).
*
* @param {import('preact-cli').Config} config - original webpack config
* @param {import('preact-cli').Env} env - current environment and options pass to the CLI
* @param {import('preact-cli').Helpers} helpers - object with useful helpers for working with the webpack config
* @param {Record<string, unknown>} options - this is mainly relevant for plugins (will always be empty in the config), default to an empty object
*/
export default (config, env, helpers, options) => {
/** you can change the config here **/
};
```

Expand Down
13 changes: 12 additions & 1 deletion docs/webpack-helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
- [getLoadersByName](#getloadersbyname)
- [getPluginsByName](#getpluginsbyname)
- [getPluginsByType](#getpluginsbytype)
- [setHtmlTemplate](#sethtmltemplate)
- [PluginWrapper](#pluginwrapper)
- [RuleWrapper](#rulewrapper)
- [LoaderWrapper](#loaderwrapper)
Expand Down Expand Up @@ -140,6 +139,18 @@ Type: [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
- `rule` **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** [rule entry](https://webpack.js.org/configuration/module/#module-rules).
- `index` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** index of rule in config.

## LoadersWrapper

Wrapper around webpack's [loader entry](https://webpack.js.org/configuration/module/#useentry).

Type: [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)

**Properties**

- `rule` **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** [rule entry](https://webpack.js.org/configuration/module/#module-rules).
- `ruleIndex` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** index of rule in config.
- `loaders` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** [loader entry](https://webpack.js.org/configuration/module/#useentry).

## LoaderWrapper

Wrapper around webpack's [loader entry](https://webpack.js.org/configuration/module/#useentry).
Expand Down
58 changes: 16 additions & 42 deletions packages/cli/lib/lib/webpack/transform-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class WebpackConfigHelpers {
* Webpack module used to create config.
*
* @readonly
* @returns {object}
* @returns {typeof webpack}
* @memberof WebpackConfigHelpers
*/
get webpack() {
Expand All @@ -160,8 +160,8 @@ class WebpackConfigHelpers {
/**
* Returns wrapper around all loaders from config.
*
* @param {object} config - [webpack config](https://webpack.js.org/configuration/#options).
* @returns {LoaderWrapper[]}
* @param {import('../../../types.js').Config} config - [webpack config](https://webpack.js.org/configuration/#options).
* @returns {import('../../../types.js').LoadersWrapper[]}
*
* @memberof WebpackConfigHelpers
*/
Expand All @@ -176,8 +176,8 @@ class WebpackConfigHelpers {
/**
* Returns wrapper around all rules from config.
*
* @param {object} config - [webpack config](https://webpack.js.org/configuration/#options).
* @returns {RuleWrapper[]}
* @param {import('../../../types.js').Config} config - [webpack config](https://webpack.js.org/configuration/#options).
* @returns {import('../../../types.js').RuleWrapper[]}
*
* @memberof WebpackConfigHelpers
*/
Expand All @@ -191,8 +191,8 @@ class WebpackConfigHelpers {
/**
* Returns wrapper around all plugins from config.
*
* @param {object} config - [webpack config](https://webpack.js.org/configuration/#options).
* @returns {PluginWrapper[]}
* @param {import('../../../types.js').Config} config - [webpack config](https://webpack.js.org/configuration/#options).
* @returns {import('../../../types.js').PluginWrapper[]}
*
* @memberof WebpackConfigHelpers
*/
Expand All @@ -201,11 +201,11 @@ class WebpackConfigHelpers {
}

/**
* Returns wrapper around all rules that match provided file.
*
*
* @param {object} config - [webpack config](https://webpack.js.org/configuration/#options).
* @param {import('../../../types.js').Config} config - [webpack config](https://webpack.js.org/configuration/#options).
* @param {string} file - path to test against loader. Resolved relatively to $PWD.
* @returns {RuleWrapper[]}
* @returns {import('../../../types.js').RuleWrapper[]}
*
* @memberof WebpackConfigHelpers
*/
Expand All @@ -221,9 +221,9 @@ class WebpackConfigHelpers {
*
* @example
* helpers.getLoadersByName(config, 'less-loader')
* @param {object} config - [webpack config](https://webpack.js.org/configuration/#options).
* @param {import('../../../types.js').Config} config - [webpack config](https://webpack.js.org/configuration/#options).
* @param {string} name - name of loader.
* @returns {LoaderWrapper[]}
* @returns {import('../../../types.js').LoaderWrapper[]}
*
* @memberof WebpackConfigHelpers
*/
Expand Down Expand Up @@ -252,9 +252,9 @@ class WebpackConfigHelpers {
*
* @example
* helpers.getPluginsByName(config, 'HtmlWebpackPlugin')
* @param {object} config - [webpack config](https://webpack.js.org/configuration/#options).
* @param {import('../../../types.js').Config} config - [webpack config](https://webpack.js.org/configuration/#options).
* @param {string} name - name of loader.
* @returns {PluginWrapper[]}
* @returns {import('../../../types.js').PluginWrapper[]}
*
* @memberof WebpackConfigHelpers
*/
Expand All @@ -270,39 +270,13 @@ class WebpackConfigHelpers {
*
* @example
* helpers.getPluginsByType(config, webpack.optimize.CommonsChunkPlugin)
* @param {object} config - [webpack config](https://webpack.js.org/configuration/#options).
* @param {import('../../../types.js').Config} config - [webpack config](https://webpack.js.org/configuration/#options).
* @param {any} type - type of plugin.
* @returns {PluginWrapper[]}
* @returns {import('../../../types.js').PluginWrapper[]}
*
* @memberof WebpackConfigHelpers
*/
getPluginsByType(config, type) {
return this.getPlugins(config).filter(w => w.plugin instanceof type);
}
}

/**
* Wrapper around webpack's [loader entry](https://webpack.js.org/configuration/module/#useentry).
*
* @typedef {object} LoaderWrapper
* @property {object} rule - [rule entry](https://webpack.js.org/configuration/module/#module-rules).
* @property {number} ruleIndex - index of rule in config.
* @property {object} loader - [loader entry](https://webpack.js.org/configuration/module/#useentry).
* @property {number} loaderIndex - index of loader in rule.
*/

/**
* Wrapper around webpack's [rule](https://webpack.js.org/configuration/module/#module-rules).
*
* @typedef {object} RuleWrapper
* @property {object} rule - [rule entry](https://webpack.js.org/configuration/module/#module-rules).
* @property {number} index - index of rule in config.
*/

/**
* Wrapper around webpack's [plugin](https://webpack.js.org/configuration/plugins/#plugins).
*
* @typedef {object} PluginWrapper
* @property {object} plugin - [plugin entry](https://webpack.js.org/configuration/plugins/#plugins).
* @property {number} index - index of plugin in config.
*/
2 changes: 2 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"bin": {
"preact": "lib/index.js"
},
"types": "types.d.ts",
"scripts": {
"pretest": "rimraf ./tests/output",
"test": "jest"
Expand Down Expand Up @@ -80,6 +81,7 @@
"@preact/async-loader": "^3.0.1",
"@prefresh/babel-plugin": "^0.4.1",
"@prefresh/webpack": "^3.2.2",
"@types/webpack": "^4.38.0",
"autoprefixer": "^10.2.5",
"babel-esm-plugin": "^0.9.0",
"babel-loader": "^8.2.2",
Expand Down
136 changes: 136 additions & 0 deletions packages/cli/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import webpack from 'webpack';

type Rule = {
test: RegExp;
[key: string]: any;
};

type RuleWrapper = {
index: number;
rule: Rule;
};

type Loader = {
loader: string;
options: Record<string, any>;
};

type LoadersWrapper = {
rule: {
test: RegExp;
[key: string]: any;
};
ruleIndex: number;
loaders: string | (string | Loader)[];
};

type LoaderWrapper = {
rule: {
test: RegExp;
[key: string]: any;
};
ruleIndex: number;
loader: string | Loader;
loaderIndex: number;
};

type Plugin = Record<string, any>;

type PluginWrapper = {
index: number;
plugin: Plugin;
};

/**
* Basic structure of config
*/
export type Config = {
resolve: {
modules: string[];
extensions: string[];
alias: string[];
};
module: {
rules: Rule[];
};
plugins: Plugin[];
mode: 'production' | 'development';
devtool: string | boolean;
output: {
filename: string;
chunkFilename: string;
publicPath: string;
[key: string]: any;
};
devServer?: Record<string, any>;
[key: string]: any;
};

/**
* Non-exhaustive list of environment conditions you may want
* to check for in your config
*/
export type Env = {
src: string;
dest: string;
esm: boolean;
sw: boolean;
dev: boolean;
production: boolean;
isProd: boolean;
ssr: boolean;
prerender: boolean;
[key: string]: any;
};
Comment on lines +59 to +70
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried to cover the commonly used ones that I've seen. Did I miss any that should be added?


export type Helpers = {
/**
* Returns Webpack module used to create config
*/
webpack: typeof webpack;

/**
* Returns wrapper around all loaders from config
*/
getLoaders(config: Config): LoadersWrapper[];

/**
* Returns wrapper around all loaders that match provided name
*
* @example helpers.getLoadersByName(config, 'babel-loader');
*/
getLoadersByName(config: Config, name: string): LoaderWrapper[];

/**
* Returns wrapper around all rules from config
*/
getRules(config: Config): RuleWrapper[];

/**
* Returns wrapper around all rules that match provided file
*
* File is resolve relative to $PWD
*
* @example helpers.getRulesByMatchingFile(config, 'src/index.js');
*/
getRulesByMatchingFile(config: Config, file: string): RuleWrapper[];

/**
* Returns wrapper around all plugins from config
*/
getPlugins(config: Config): PluginWrapper[];

/**
* Returns wrapper around all plugins that match provided name
*
* @example helpers.getPluginsByName(config, 'Critters');
*/
getPluginsByName(config: Config, name: string): PluginWrapper[];

/**
* Returns wrapper around all plugins that match provided type
*
* @example helpers.getPluginsByType(config, webpack.DefinePlugin);
*/
getPluginsByType(config: Config, type: any): PluginWrapper[];
};
Loading