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

grafana/toolkit: Add option to override webpack config #20872

Merged

Conversation

sebimarkgraf
Copy link
Contributor

What this PR does / why we need it:
Implement possible option for #20833 to allow user to override webpack configuration.
This is a WIP and is intended to show a possible implementation

Fixes #20833

@sebimarkgraf sebimarkgraf force-pushed the feature/20833-override-webpack-config branch from f329cd2 to 951833d Compare December 4, 2019 15:27
@sebimarkgraf sebimarkgraf force-pushed the feature/20833-override-webpack-config branch 2 times, most recently from d0ac1a2 to a98163a Compare December 4, 2019 15:38
@dprokop dprokop self-requested a review December 5, 2019 08:22
@dprokop
Copy link
Member

dprokop commented Dec 5, 2019

@Sintifo thanks for this. I'm gonna take a look at this tomorrow morning and come back with some feedback

@stevenvachon
Copy link
Contributor

@Sintifo my comment is awaiting an answer. This PR may not be the best approach.

@sebimarkgraf sebimarkgraf force-pushed the feature/20833-override-webpack-config branch from a98163a to bd1104f Compare December 6, 2019 09:30
@sebimarkgraf
Copy link
Contributor Author

@stevenvachon I updated the PR to your suggested approach.

This allows the user to implement the getWebpackConfig function themselves, while keeping the possibility to change the configuration depending on the options.

Example:

import { getWebpackConfig as originalGetter, WebpackConfigurationGetter } from '@grafana/toolkit/src/config'
import WorkerPlugin from 'worker-plugin';

export const getWebpackConfig: WebpackConfigurationGetter = (options) => {
    const webpackConfig = originalGetter(options);
    console.log('Custom config');

    webpackConfig.plugins.push(new WorkerPlugin())

    return webpackConfig;
}

I am not sure how you generate the index.ts for top-level imports. When trying to build the toolkit I didn't get any in the dist directory.

I thought about using dynamic await import but sticked to require since that seems to be the way is was done everywhere else.

@dprokop
Copy link
Member

dprokop commented Dec 6, 2019

Regarding this API:

export const getWebpackConfig: WebpackConfigurationGetter = (options) => {

I think this function should get a default toolkit's webpack config object as an argument so that you don't need getWebpackConfig exposed from toolkit.

@sebimarkgraf sebimarkgraf force-pushed the feature/20833-override-webpack-config branch from bd1104f to de30f59 Compare December 6, 2019 12:53
@sebimarkgraf
Copy link
Contributor Author

@dprokop
Changed to your suggestion. Is it wise to use a default export instead to remove the need for correct naming?

import { CustomWebpackConfigurationGetter } from '@grafana/toolkit/src/config'
import WorkerPlugin from 'worker-plugin';

export const getWebpackConfig: CustomWebpackConfigurationGetter = (defaultConfig, options) => {
    console.log('Custom config');
    
    defaultConfig.plugins.push(new WorkerPlugin())

    return defaultConfig;
}

@papagian papagian added the pr/external This PR is from external contributor label Dec 8, 2019
@dprokop
Copy link
Member

dprokop commented Dec 9, 2019

Changed to your suggestion. Is it wise to use a default export instead to remove the need for correct naming?

What do you mean, the path @grafana/toolkit/src/config? We don't use default exports in our packages. For this particular case I would stick with the full path import as you did now. The only thing I would introduce is the index.ts file under '@grafana/toolkit/src/config' path, so that you don't need to import from @grafana/toolkit/src/config/webpack.plugin.config.

const customWebpackPath = path.resolve(process.cwd(), 'webpack.plugin.config.ts');
if (fs.existsSync(customWebpackPath)) {
const customConfig = require(customWebpackPath) as { getWebpackConfig: CustomWebpackConfigurationGetter };
return customConfig.getWebpackConfig(baseConfig, options);
Copy link
Member

Choose a reason for hiding this comment

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

Having a meaningful error message in the console would be wise if the exported thing is not a function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added error if export is not a function.

@sebimarkgraf sebimarkgraf force-pushed the feature/20833-override-webpack-config branch from de30f59 to 0bafec8 Compare December 10, 2019 08:27
@sebimarkgraf
Copy link
Contributor Author

Added a example in the README to be easier to use

@sebimarkgraf sebimarkgraf changed the title WIP: Toolkit: Add option to override webpack config Toolkit: Add option to override webpack config Dec 10, 2019
@stevenvachon
Copy link
Contributor

stevenvachon commented Dec 10, 2019

I think that this approach too is overly complicated. Why don't we let plugin authors create their own 100% custom config? For example, they may prefer JavaScript over TypeScript. Is there an issue with allowing them to import the toolkit's default config and let them extend it themselves?:

import defaultConfig from '@grafana/toolkit/webpack-config'; // or similar
import {mergeDeep} from 'lodash';
export default mergeDeep({}, defaultConfig, {...});

@ryantxu
Copy link
Member

ryantxu commented Dec 10, 2019

Why don't we let plugin authors create their own 100% custom config?

100% we do... you just don't have to use toolkit and put in your own system (webpack, grunt, rollup, whatever). The trick with toolkit is allowing people to extend only a little bit.

Here is a project with a complete webpack implementation:
https://github.com/NatelEnergy/grafana-plotly-panel

or grunt:
https://github.com/grafana/simple-json-datasource

export const loadWebpackConfig: WebpackConfigurationGetter = options => {
const baseConfig = getBaseWebpackConfig(options);

const customWebpackPath = path.resolve(process.cwd(), 'webpack.plugin.config.ts');
Copy link
Member

Choose a reason for hiding this comment

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

Why not naming this file webpack.config.ts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to differ it from the default naming of webpack.
If we use the default webpack.config.ts everybody expects a custom config as proposed by steven.

@dprokop
Copy link
Member

dprokop commented Dec 11, 2019

@stevenvachon goal with toolkit is to have a sane common config that addresses most of the use cases. I think that with this change we introduce a "safe" way of extending the basic config, without the need of creating a complete custom one. It does not differ much from what you are suggesting with merging the configs, but it has advantage of the config being typed(with WebpackConfigurationGetter) so working with it could be easier.

@sebimarkgraf
Copy link
Contributor Author

@stevenvachon This approach would require the config to be more static. Currently the config depends on the given options for production and watching.

@dprokop
Copy link
Member

dprokop commented Dec 12, 2019

@sebimarkgraf this seems close to mergeable. I would love to see a test verifying that it actually works. You can take some inspiration from the tests and mocks that are implemented in toolkit's config directory.

Also - did you have a chance to test it with the actual custom config?

@sebimarkgraf
Copy link
Contributor Author

@dprokop I tested it to add another plugin for my own config. I will create a test and update the PR then.

@sebimarkgraf sebimarkgraf force-pushed the feature/20833-override-webpack-config branch 2 times, most recently from 22debd8 to 9cee96b Compare December 12, 2019 15:22
@sebimarkgraf
Copy link
Contributor Author

@dprokop Updated with test cases.
If you don't have any more wishes, it is ready to be merged from my side.

export type CustomWebpackConfigurationGetter = (
originalConfig: webpack.Configuration,
options: WebpackConfigurationOptions
) => webpack.Configuration;

export const findModuleFiles = (base: string, files?: string[], result?: string[]) => {
files = files || fs.readdirSync(base);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to use the async version of this function instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This would make sense if we have any tasks after the webpack task.

This would require to have the complete loading async and therefore add a lot of noise to this PR.
If you want I can still change everything to async/await.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's probably not critical for this PR, but async functions are a Node.js best practice.

@sebimarkgraf sebimarkgraf force-pushed the feature/20833-override-webpack-config branch from 9cee96b to f3b7b63 Compare December 13, 2019 09:20
@sebimarkgraf
Copy link
Contributor Author

Added async/await as additional commit

@sebimarkgraf sebimarkgraf force-pushed the feature/20833-override-webpack-config branch from 175eb3f to 736deeb Compare December 16, 2019 12:31
@@ -127,6 +127,27 @@ Currently we support following Jest configuration properties:
- [`snapshotSerializers`](https://jest-bot.github.io/jest/docs/configuration.html#snapshotserializers-array-string)
- [`moduleNameMapper`](https://jestjs.io/docs/en/configuration#modulenamemapper-object-string-string)

### Can I add custom Webpack rules or plugins?
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
### Can I add custom Webpack rules or plugins?
### How can I customize Webpack rules or plugins?

@dprokop
Copy link
Member

dprokop commented Dec 16, 2019

@sebimarkgraf I've had a chance to test your implementation today and it works great, thanks for this!

Some final remarks:

  1. export = getWebpackConfig this got me confused as by default I did export const getWebpackConfiguration which made the build break. I think we should add support for named export from the custom webpack config file.
  2. I'm still not sold on the webpack.plugin.config.ts file name. That's probably only me, but I would expect it to be webpack.config.ts as we use this convention for prettier and tsconfig (eslint soon TSLint → ESLint #21006). There are 2 opinions agains mine in the PR so let's stick with the name you have proposed.
  3. Left some minor comment about documentation. When you fix 1. then pls also update the docs and we are good to merge.

@dprokop dprokop changed the title Toolkit: Add option to override webpack config grafana/toolkit: Add option to override webpack config Dec 16, 2019
@dprokop dprokop added this to the 6.6 milestone Dec 16, 2019
@sebimarkgraf
Copy link
Contributor Author

Your argument of aligning all configurations with the original name is quite compelling. Since stevenvachon does not seem to take a definite side, I will change the naming.

@stevenvachon stevenvachon merged commit f1845d8 into grafana:master Dec 18, 2019
ryantxu pushed a commit that referenced this pull request Dec 18, 2019
* Toolkit: Add possibility to add custom webpack config

* Toolkit: Refactor webpack to utilize async-await

* Toolkit: Rename config file and allow named export
ryantxu pushed a commit to ryantxu/grafana that referenced this pull request Dec 23, 2019
* Toolkit: Add possibility to add custom webpack config

* Toolkit: Refactor webpack to utilize async-await

* Toolkit: Rename config file and allow named export
johntdyer pushed a commit to johntdyer/grafana that referenced this pull request Jan 2, 2020
* Toolkit: Add possibility to add custom webpack config

* Toolkit: Refactor webpack to utilize async-await

* Toolkit: Rename config file and allow named export
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Grafana Toolkit: Allow to extend webpack configuration
5 participants