Skip to content

Commit 9a8303d

Browse files
committed
feat(#94): enables compatibility with webpack 5
1 parent 47f65a8 commit 9a8303d

File tree

16 files changed

+604
-28
lines changed

16 files changed

+604
-28
lines changed

.github/workflows/cypress.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,12 @@ jobs:
7676
start: yarn serve -l 8994 ./dist
7777
env:
7878
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
79+
- uses: cypress-io/github-action@v2
80+
with:
81+
group: app-config-webpack5
82+
working-directory: tests/webpack-projects/webpack5
83+
install: false
84+
record: true
85+
start: yarn serve -l 8995 ./dist
86+
env:
87+
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

app-config-webpack/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@
3535
},
3636
"peerDependencies": {
3737
"@app-config/main": "^2.3.4",
38-
"html-webpack-plugin": "4",
39-
"webpack": "4"
38+
"html-webpack-plugin": "4 || 5",
39+
"webpack": "4 || 5"
4040
},
4141
"devDependencies": {
4242
"@app-config/main": "^2.3.4",
4343
"@types/loader-utils": "1",
44-
"html-webpack-plugin": "4",
45-
"webpack": "4"
44+
"@webpack-cli/serve": "1",
45+
"html-webpack-plugin": "5",
46+
"webpack": "5"
4647
},
4748
"prettier": "@lcdev/prettier",
4849
"jest": {

app-config-webpack/src/index.test.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ describe('frontend-webpack-project example', () => {
2929
it('builds the project without header injection', async () => {
3030
await new Promise<void>((done, reject) => {
3131
webpack([createOptions({})], (err, stats) => {
32-
if (err) reject(err);
32+
if (err) return reject(err);
33+
if (!stats) return reject(new Error('no stats'));
3334
if (stats.hasErrors()) reject(stats.toString());
3435

3536
const { children } = stats.toJson();
@@ -51,7 +52,8 @@ describe('frontend-webpack-project example', () => {
5152

5253
await new Promise<void>((done, reject) => {
5354
webpack([createOptions({})], (err, stats) => {
54-
if (err) reject(err);
55+
if (err) return reject(err);
56+
if (!stats) return reject(new Error('no stats'));
5557
if (stats.hasErrors()) reject(stats.toString());
5658

5759
const { children } = stats.toJson();
@@ -73,7 +75,8 @@ describe('frontend-webpack-project example', () => {
7375

7476
await new Promise<void>((done, reject) => {
7577
webpack([createOptions({ noGlobal: true })], (err, stats) => {
76-
if (err) reject(err);
78+
if (err) return reject(err);
79+
if (!stats) return reject(new Error('no stats'));
7780
if (stats.hasErrors()) reject(stats.toString());
7881

7982
const { children } = stats.toJson();
@@ -97,7 +100,8 @@ describe('frontend-webpack-project example', () => {
97100

98101
await new Promise<void>((done, reject) => {
99102
webpack([createOptions({ intercept: /@app-config\/main/ })], (err, stats) => {
100-
if (err) reject(err);
103+
if (err) return reject(err);
104+
if (!stats) return reject(new Error('no stats'));
101105
if (stats.hasErrors()) reject(stats.toString());
102106

103107
const { children } = stats.toJson();
@@ -121,7 +125,8 @@ describe('frontend-webpack-project example', () => {
121125
new Promise<void>((done, reject) => {
122126
webpack([createOptions({})], (err, stats) => {
123127
if (err) return reject(err);
124-
if (stats.hasErrors()) return reject(stats.toString());
128+
if (!stats) return reject(new Error('no stats'));
129+
if (stats.hasErrors()) reject(stats.toString());
125130

126131
done();
127132
});
@@ -136,7 +141,8 @@ describe('frontend-webpack-project example', () => {
136141
webpack(
137142
[createOptions({ loading: { environmentVariableName: 'MY_CONFIG' } })],
138143
(err, stats) => {
139-
if (err) reject(err);
144+
if (err) return reject(err);
145+
if (!stats) return reject(new Error('no stats'));
140146
if (stats.hasErrors()) reject(stats.toString());
141147

142148
const { children } = stats.toJson();
@@ -159,7 +165,8 @@ describe('frontend-webpack-project example', () => {
159165

160166
await new Promise<void>((done, reject) => {
161167
webpack([createOptions({}, true)], (err, stats) => {
162-
if (err) reject(err);
168+
if (err) return reject(err);
169+
if (!stats) return reject(new Error('no stats'));
163170
if (stats.hasErrors()) reject(stats.toString());
164171

165172
const { children } = stats.toJson();

app-config-webpack/src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ export default class AppConfigPlugin {
6464
// eslint-disable-next-line no-param-reassign
6565
resolve.request = `${join(__dirname, '..', '.config-placeholder')}?${queryString}`;
6666
}
67-
68-
return resolve;
6967
},
7068
);
7169
});
@@ -84,6 +82,7 @@ export default class AppConfigPlugin {
8482
attributes: { id: 'app-config', type: 'text/javascript' },
8583
innerHTML: ``,
8684
voidTag: false,
85+
meta: {},
8786
});
8887

8988
return {

app-config-webpack/src/loader.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import * as wp from 'webpack';
21
import { getOptions, parseQuery } from 'loader-utils';
32
import { loadValidatedConfig } from '@app-config/main';
43
import type { Options } from './index';
54

5+
type LoaderContext = Parameters<typeof getOptions>[0];
6+
interface Loader extends LoaderContext {}
7+
68
const privateName = '_appConfig';
79

8-
const loader: wp.loader.Loader = function AppConfigLoader() {
10+
const loader = function AppConfigLoader(this: Loader) {
911
if (this.cacheable) this.cacheable();
1012

1113
const callback = this.async()!;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"projectId": "fm6zcy",
3+
"baseUrl": "http://localhost:8995"
4+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import '@app-config/cypress';
2+
import config from '@app-config/main';
3+
4+
describe('Config Loading', () => {
5+
it('should render the configuration', () => {
6+
cy.visit('/');
7+
8+
cy.get('body').should('contain', `"urlProperty": "https://example.com"`);
9+
cy.get('body').should(
10+
'contain',
11+
`"longStringProperty": "some long string with a \\" char and '\\\\n"`,
12+
);
13+
});
14+
15+
it('should mock the configuration value', () => {
16+
cy.setAppConfig({
17+
urlProperty: 'https://overwritten.com',
18+
longStringProperty: 'shorter than before',
19+
});
20+
21+
cy.visit('/');
22+
23+
cy.get('body').should('contain', `"urlProperty": "https://overwritten.com"`);
24+
cy.get('body').should('contain', `"longStringProperty": "shorter than before"`);
25+
});
26+
27+
it('should fail when overriden with an invalid value', () => {
28+
cy.setAppConfig({
29+
urlProperty: 'https://overwritten.com',
30+
longStringProperty: 'short!',
31+
});
32+
33+
cy.visit('/');
34+
35+
cy.get('body').should('contain', `Config Error: should NOT have fewer than 10 characters`);
36+
});
37+
38+
it('uses config from webpack preprocessor', () => {
39+
cy.setAppConfig(config);
40+
cy.visit('/');
41+
42+
cy.get('body').should('contain', `"urlProperty": "https://example.com"`);
43+
cy.get('body').should(
44+
'contain',
45+
`"longStringProperty": "some long string with a \\" char and '\\\\n"`,
46+
);
47+
});
48+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const webpackPreprocessor = require('@cypress/webpack-preprocessor');
2+
const { default: AppConfigPlugin } = require('@app-config/webpack');
3+
4+
module.exports = (on) => {
5+
const options = {
6+
webpackOptions: {
7+
mode: 'development',
8+
module: {
9+
rules: [
10+
{ test: AppConfigPlugin.regex, use: { loader: AppConfigPlugin.loader } },
11+
{
12+
test: /\.jsx?$/,
13+
exclude: [/node_modules/],
14+
use: [
15+
{
16+
loader: 'babel-loader',
17+
options: {
18+
presets: ['@babel/preset-env'],
19+
},
20+
},
21+
],
22+
},
23+
{
24+
test: /\.tsx?$/,
25+
use: 'ts-loader',
26+
exclude: /node_modules/,
27+
},
28+
],
29+
},
30+
plugins: [new AppConfigPlugin()],
31+
},
32+
};
33+
34+
on('file:preprocessor', webpackPreprocessor(options));
35+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require('@app-config/cypress').register();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "../tsconfig.json",
3+
"compilerOptions": {
4+
"types": ["cypress"],
5+
"rootDir": "."
6+
},
7+
"include": [
8+
"./*/*.ts",
9+
"../src/@types"
10+
]
11+
}

0 commit comments

Comments
 (0)