Skip to content

Commit

Permalink
Toolkit: Refactor webpack to utilize async-await
Browse files Browse the repository at this point in the history
  • Loading branch information
sebimarkgraf committed Dec 16, 2019
1 parent f3b7b63 commit 736deeb
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 22 deletions.
2 changes: 1 addition & 1 deletion packages/grafana-toolkit/src/cli/tasks/plugin/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface PluginBundleOptions {
// export const bundlePlugin = useSpinner<PluginBundleOptions>('Bundle plugin', ({ watch }) => {
export const bundlePlugin = async ({ watch, production }: PluginBundleOptions) => {
const compiler = webpack(
loadWebpackConfig({
await loadWebpackConfig({
watch,
production,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,39 @@ describe('Plugin webpack config', () => {
jest.restoreAllMocks();
});

it('finds module.ts and module.tsx files', () => {
const moduleFiles = findModuleFiles('/', modulePathsMock);
it('finds module.ts and module.tsx files', async () => {
const moduleFiles = await findModuleFiles('/', modulePathsMock);
expect(moduleFiles.length).toBe(2);
expect(moduleFiles).toEqual(['/some/path/module.ts', '/some/path/module.tsx']);
});
});

describe('loadWebpackConfig', () => {
beforeAll(() => {
jest.spyOn(webpackConfig, 'findModuleFiles').mockReturnValue([]);
jest.spyOn(webpackConfig, 'findModuleFiles').mockReturnValue(new Promise((res, _) => res([])));
});

afterAll(() => {
jest.restoreAllMocks();
});

it('uses default config if no override exists', () => {
it('uses default config if no override exists', async () => {
const spy = jest.spyOn(process, 'cwd');
spy.mockReturnValue(`${__dirname}/mocks/webpack/noOverride/`);
loadWebpackConfig({});
await loadWebpackConfig({});
});

it('calls customConfig if it exists', () => {
it('calls customConfig if it exists', async () => {
const spy = jest.spyOn(process, 'cwd');
spy.mockReturnValue(`${__dirname}/mocks/webpack/overrides/`);
const config = loadWebpackConfig({});
const config = await loadWebpackConfig({});
expect(config.name).toBe('customConfig');
});

it('throws an error if module does not export function', () => {
it('throws an error if module does not export function', async () => {
const spy = jest.spyOn(process, 'cwd');
spy.mockReturnValue(`${__dirname}/mocks/webpack/unsupportedOverride/`);
expect(() => loadWebpackConfig({})).toThrowError();
await expect(loadWebpackConfig({})).rejects.toThrowError();
});
});
});
28 changes: 16 additions & 12 deletions packages/grafana-toolkit/src/config/webpack.plugin.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const fs = require('fs');
const util = require('util');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ReplaceInFileWebpackPlugin = require('replace-in-file-webpack-plugin');
Expand All @@ -7,28 +8,31 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const readdirPromise = util.promisify(fs.readdir);
const accessPromise = util.promisify(fs.access);

import * as webpack from 'webpack';
import { getStyleLoaders, getStylesheetEntries, getFileLoaders } from './webpack/loaders';

export interface WebpackConfigurationOptions {
watch?: boolean;
production?: boolean;
}
type WebpackConfigurationGetter = (options: WebpackConfigurationOptions) => webpack.Configuration;
type WebpackConfigurationGetter = (options: WebpackConfigurationOptions) => Promise<webpack.Configuration>;
export type CustomWebpackConfigurationGetter = (
originalConfig: webpack.Configuration,
options: WebpackConfigurationOptions
) => webpack.Configuration;

export const findModuleFiles = (base: string, files?: string[], result?: string[]) => {
files = files || fs.readdirSync(base);
export const findModuleFiles = async (base: string, files?: string[], result?: string[]) => {
files = files || (await readdirPromise(base));
result = result || [];

if (files) {
files.forEach(file => {
files.forEach(async file => {
const newbase = path.join(base, file);
if (fs.statSync(newbase).isDirectory()) {
result = findModuleFiles(newbase, fs.readdirSync(newbase), result);
result = await findModuleFiles(newbase, await readdirPromise(newbase), result);
} else {
const filename = path.basename(file);
if (/^module.(t|j)sx?$/.exec(filename)) {
Expand Down Expand Up @@ -60,9 +64,9 @@ const getManualChunk = (id: string) => {
return null;
};

const getEntries = () => {
const getEntries = async () => {
const entries: { [key: string]: string } = {};
const modules = getModuleFiles();
const modules = await getModuleFiles();

modules.forEach(modFile => {
const mod = getManualChunk(modFile);
Expand Down Expand Up @@ -118,7 +122,7 @@ const getCommonPlugins = (options: WebpackConfigurationOptions) => {
];
};

const getBaseWebpackConfig: WebpackConfigurationGetter = options => {
const getBaseWebpackConfig: WebpackConfigurationGetter = async options => {
const plugins = getCommonPlugins(options);
const optimization: { [key: string]: any } = {};

Expand All @@ -138,7 +142,7 @@ const getBaseWebpackConfig: WebpackConfigurationGetter = options => {
},
context: path.join(process.cwd(), 'src'),
devtool: 'source-map',
entry: getEntries(),
entry: await getEntries(),
output: {
filename: '[name].js',
path: path.join(process.cwd(), 'dist'),
Expand Down Expand Up @@ -229,12 +233,12 @@ const getBaseWebpackConfig: WebpackConfigurationGetter = options => {
};
};

export const loadWebpackConfig: WebpackConfigurationGetter = options => {
const baseConfig = getBaseWebpackConfig(options);
export const loadWebpackConfig: WebpackConfigurationGetter = async options => {
const baseConfig = await getBaseWebpackConfig(options);
const customWebpackPath = path.resolve(process.cwd(), 'webpack.plugin.config.ts');

try {
fs.accessSync(customWebpackPath);
await accessPromise(customWebpackPath);
const customConfig = require(customWebpackPath);
if (typeof customConfig !== 'function') {
throw Error('Custom webpack config needs to export a function implementing CustomWebpackConfigurationGetter ');
Expand Down

0 comments on commit 736deeb

Please sign in to comment.