@patternfly/documentation-framework 2.0.0-alpha.3 → 2.0.0-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/app.js +12 -11
  3. package/components/cssVariables/cssSearch.js +3 -4
  4. package/components/cssVariables/cssVariables.js +69 -67
  5. package/components/functionsTable/functionsTable.js +57 -0
  6. package/components/propsTable/propsTable.js +85 -79
  7. package/components/sectionGallery/sectionDataListLayout.js +67 -0
  8. package/components/sectionGallery/sectionGallery.css +44 -0
  9. package/components/sectionGallery/sectionGallery.js +53 -0
  10. package/components/sectionGallery/sectionGalleryLayout.js +37 -0
  11. package/components/sectionGallery/sectionGalleryToolbar.js +30 -0
  12. package/components/sectionGallery/sectionGalleryWrapper.js +89 -0
  13. package/components/sideNav/sideNav.js +10 -3
  14. package/helpers/getTitle.js +2 -2
  15. package/layouts/sideNavLayout/sideNavLayout.css +0 -4
  16. package/layouts/sideNavLayout/sideNavLayout.js +48 -35
  17. package/package.json +28 -25
  18. package/pages/404/index.js +3 -3
  19. package/routes.js +19 -5
  20. package/scripts/cli/build.js +6 -0
  21. package/scripts/cli/cli.js +2 -0
  22. package/scripts/cli/generate.js +2 -2
  23. package/scripts/cli/start.js +6 -8
  24. package/scripts/md/parseMD.js +40 -8
  25. package/scripts/tsDocgen.js +119 -91
  26. package/scripts/typeDocGen.js +209 -0
  27. package/scripts/webpack/webpack.base.config.js +34 -32
  28. package/scripts/webpack/webpack.client.config.js +11 -8
  29. package/scripts/webpack/webpack.server.config.js +8 -5
  30. package/scripts/writeScreenshots.js +2 -2
  31. package/templates/html.ejs +1 -3
  32. package/templates/mdx.css +0 -5
  33. package/templates/mdx.js +58 -41
  34. package/templates/patternfly-docs/content/extensions/extension/design-guidelines/design-guidelines.md +2 -0
  35. package/templates/patternfly-docs/content/extensions/extension/examples/basic.md +2 -0
  36. package/versions.json +29 -9
@@ -1,28 +1,28 @@
1
- const fs = require('fs');
2
- const reactDocgen = require('react-docgen');
3
- const ts = require('typescript');
1
+ const fs = require("fs");
2
+ const reactDocgen = require("react-docgen");
3
+ const ts = require("typescript");
4
4
 
5
5
  const annotations = [
6
6
  {
7
7
  regex: /@deprecated/,
8
- name: 'deprecated',
9
- type: 'Boolean'
8
+ name: "deprecated",
9
+ type: "Boolean",
10
10
  },
11
11
  {
12
12
  regex: /@hide/,
13
- name: 'hide',
14
- type: 'Boolean'
13
+ name: "hide",
14
+ type: "Boolean",
15
15
  },
16
16
  {
17
17
  regex: /@beta/,
18
- name: 'beta',
19
- type: 'Boolean'
18
+ name: "beta",
19
+ type: "Boolean",
20
20
  },
21
21
  {
22
22
  regex: /@propType\s+(.*)/,
23
- name: 'type',
24
- type: 'String'
25
- }
23
+ name: "type",
24
+ type: "String",
25
+ },
26
26
  ];
27
27
 
28
28
  function addAnnotations(prop) {
@@ -30,12 +30,12 @@ function addAnnotations(prop) {
30
30
  annotations.forEach(({ regex, name }) => {
31
31
  const match = prop.description.match(regex);
32
32
  if (match) {
33
- prop.description = prop.description.replace(regex, '').trim();
33
+ prop.description = prop.description.replace(regex, "").trim();
34
34
  if (name) {
35
35
  prop[name] = match[2] || match[1] || true;
36
36
  }
37
37
  }
38
- })
38
+ });
39
39
  }
40
40
 
41
41
  return prop;
@@ -55,74 +55,101 @@ function getComponentMetadata(filename, sourceText) {
55
55
  // console.warn(`No component found in ${filename}:`, err);
56
56
  }
57
57
 
58
- return (parsedComponents || []).filter(parsed => parsed && parsed.displayName);
58
+ return (parsedComponents || []).filter(
59
+ (parsed) => parsed && parsed.displayName
60
+ );
59
61
  }
60
62
 
61
- function getInterfaceMetadata(filename, sourceText) {
62
- const ast = ts.createSourceFile(
63
+ const getNodeText = (node, sourceText) => {
64
+ if (!node || !node.pos || !node.end) {
65
+ return undefined;
66
+ }
67
+
68
+ return sourceText.substring(node.pos, node.end).trim();
69
+ };
70
+
71
+ const buildJsDocProps = (nodes, sourceText) =>
72
+ nodes?.reduce((acc, member) => {
73
+ const name =
74
+ (member.name && member.name.escapedText) ||
75
+ (member.parameters &&
76
+ `[${getNodeText(member.parameters[0], sourceText)}]`) ||
77
+ "Unknown";
78
+ acc[name] = {
79
+ description: member.jsDoc
80
+ ? member.jsDoc.map((doc) => doc.comment).join("\n")
81
+ : null,
82
+ required: member.questionToken === undefined,
83
+ type: {
84
+ raw: getNodeText(member.type, sourceText).trim(),
85
+ },
86
+ };
87
+ return acc;
88
+ }, {});
89
+
90
+ const getSourceFileStatements = (filename, sourceText) => {
91
+ const { statements } = ts.createSourceFile(
63
92
  filename,
64
93
  sourceText,
65
94
  ts.ScriptTarget.Latest // languageVersion
66
95
  );
67
-
68
- function getText(node) {
69
- if (!node || !node.pos || !node.end) {
70
- return undefined;
71
- }
72
- return sourceText.substring(node.pos, node.end).trim();
73
- }
74
96
 
75
- const interfaces = [];
76
-
77
- ast.statements
78
- .filter(statement => statement.kind === ts.SyntaxKind.InterfaceDeclaration)
79
- .forEach(statement => {
80
- const props = statement.members.reduce((acc, member) => {
81
- const name = (member.name && member.name.escapedText)
82
- || (member.parameters && `[${getText(member.parameters[0])}]`)
83
- || 'Unknown';
84
- acc[name] = {
85
- description: member.jsDoc
86
- ? member.jsDoc.map(doc => doc.comment).join('\n')
87
- : null,
88
- required: member.questionToken === undefined,
89
- type: {
90
- raw: getText(member.type).trim()
97
+ return statements;
98
+ };
99
+
100
+ const getInterfaceMetadata = (filename, sourceText) =>
101
+ getSourceFileStatements(filename, sourceText).reduce(
102
+ (metaDataAcc, statement) => {
103
+ if (statement.kind === ts.SyntaxKind.InterfaceDeclaration) {
104
+ metaDataAcc.push({
105
+ displayName: statement.name.escapedText,
106
+ description: statement.jsDoc?.map((doc) => doc.comment).join("\n"),
107
+ props: buildJsDocProps(statement.members, sourceText),
108
+ });
109
+ }
110
+
111
+ return metaDataAcc;
112
+ },
113
+ []
114
+ );
115
+
116
+ const getTypeAliasMetadata = (filename, sourceText) =>
117
+ getSourceFileStatements(filename, sourceText).reduce(
118
+ (metaDataAcc, statement) => {
119
+ if (statement.kind === ts.SyntaxKind.TypeAliasDeclaration) {
120
+ const props = statement.type.types?.reduce((propAcc, type) => {
121
+ if (type.members) {
122
+ propAcc.push(buildJsDocProps(type.members, sourceText));
91
123
  }
92
- };
93
- return acc;
94
- }, {});
95
-
96
- interfaces.push({
97
- displayName: statement.name.escapedText,
98
- description: statement.jsDoc
99
- ? statement.jsDoc.map(doc => doc.comment).join('\n')
100
- : null,
101
- props
102
- });
103
- });
104
- return interfaces;
105
- }
124
+
125
+ return propAcc;
126
+ }, []);
127
+
128
+ metaDataAcc.push({
129
+ props,
130
+ displayName: statement.name.escapedText,
131
+ description: statement.jsDoc?.map((doc) => doc.comment).join("\n"),
132
+ });
133
+ }
134
+
135
+ return metaDataAcc;
136
+ },
137
+ []
138
+ );
106
139
 
107
140
  function normalizeProp([
108
141
  name,
109
- {
110
- required,
111
- annotatedType,
112
- type,
113
- tsType,
114
- description,
115
- defaultValue
116
- }
142
+ { required, annotatedType, type, tsType, description, defaultValue },
117
143
  ]) {
118
144
  const res = {
119
145
  name,
120
- type: annotatedType
121
- || (type && type.name)
122
- || (type && (type.raw || type.name))
123
- || (tsType && (tsType.raw || tsType.name))
124
- || 'No type info',
125
- description
146
+ type:
147
+ annotatedType ||
148
+ (type && type.name) ||
149
+ (type && (type.raw || type.name)) ||
150
+ (tsType && (tsType.raw || tsType.name)) ||
151
+ "No type info",
152
+ description,
126
153
  };
127
154
  if (required) {
128
155
  res.required = true;
@@ -134,45 +161,46 @@ function normalizeProp([
134
161
  return res;
135
162
  }
136
163
 
137
- function getDescription(parsed, ) {
138
-
139
- }
140
-
141
164
  function tsDocgen(file) {
142
- const sourceText = fs.readFileSync(file, 'utf8');
165
+ const sourceText = fs.readFileSync(file, "utf8");
143
166
  const componentMeta = getComponentMetadata(file, sourceText); // Array of components with props
144
167
  const interfaceMeta = getInterfaceMetadata(file, sourceText); // Array of interfaces with props
145
- const interfaceMetaMap = interfaceMeta.reduce(function(target, interface) {
146
- target[interface.displayName] = interface;
168
+ const typeAliasMeta = getTypeAliasMetadata(file, sourceText); // Array of type aliases with props
169
+ const propsMetaMap = [...interfaceMeta, ...typeAliasMeta].reduce(function (
170
+ target,
171
+ interfaceOrTypeAlias
172
+ ) {
173
+ target[interfaceOrTypeAlias.displayName] = interfaceOrTypeAlias;
147
174
  return target;
148
- }, {})
175
+ },
176
+ {});
149
177
 
150
- // Go through each component and check if they have an interface with a jsDoc description
178
+ // Go through each component and check if they have an interface or type alias with a jsDoc description
151
179
  // If so copy it over (fix for https://github.com/patternfly/patternfly-react/issues/7612)
152
- componentMeta.forEach(c => {
180
+ componentMeta.forEach((c) => {
153
181
  if (c.description) {
154
182
  return c;
155
183
  }
156
- const interface = `${c.displayName}Props`;
157
- if (interfaceMetaMap[interface] && interfaceMetaMap[interface].description) {
158
- c.description = interfaceMetaMap[interface].description;
184
+
185
+ const propsName = `${c.displayName}Props`;
186
+ if (propsMetaMap[propsName]?.description) {
187
+ c.description = propsMetaMap[propsName].description;
159
188
  }
160
- })
189
+ });
161
190
 
162
- return componentMeta
163
- .concat(interfaceMeta)
164
- .map(parsed => ({
191
+ return [...componentMeta, ...interfaceMeta, ...typeAliasMeta].map(
192
+ (parsed) => ({
165
193
  name: parsed.displayName,
166
- description: parsed.description || '',
194
+ description: parsed.description || "",
167
195
  props: Object.entries(parsed.props || {})
168
196
  .map(normalizeProp)
169
197
  .map(addAnnotations)
170
- .filter(prop => !prop.hide)
171
- .sort((p1, p2) => p1.name.localeCompare(p2.name))
172
- }));
198
+ .filter((prop) => !prop.hide)
199
+ .sort((p1, p2) => p1.name.localeCompare(p2.name)),
200
+ })
201
+ );
173
202
  }
174
203
 
175
204
  module.exports = {
176
- tsDocgen
205
+ tsDocgen,
177
206
  };
178
-
@@ -0,0 +1,209 @@
1
+ const TypeDoc = require("typedoc");
2
+ const path = require("path");
3
+
4
+ /** Compiles variable types if a type is generic. */
5
+ function getVariableType(typeArguments) {
6
+ if (!typeArguments || typeArguments.length === 0) {
7
+ return "";
8
+ }
9
+
10
+ const typeArgs = typeArguments.map((type) => getType(type));
11
+
12
+ return (
13
+ typeArgs.reduce((acc, type) => acc + type + ", ", "<").slice(0, -2) + ">"
14
+ );
15
+ }
16
+
17
+ /** compiles key/value pairs of a Type or Interface. */
18
+ function getPropertyTypes(properties) {
19
+ const formattedProperties = properties.reduce((acc, property) => {
20
+ const { flags, name, type } = property;
21
+ const formattedName = flags.isOptional ? name + "?" : name;
22
+ return `${acc}${formattedName}: ${getType(type)}; `;
23
+ }, "");
24
+
25
+ return `{ ${formattedProperties} }`;
26
+ }
27
+
28
+ /** Compiles the subtypes of a tuple. */
29
+ function getTupleTypes(tupleElements) {
30
+ const [firstType, secondType] = tupleElements.map((element) =>
31
+ getType(element)
32
+ );
33
+ return `[${firstType}, ${secondType}]`;
34
+ }
35
+
36
+ /** Compiles the different subtypes of a union or intersection. */
37
+ function getJoinedTypes(types, joinChar) {
38
+ const joinedTypes = types.map((type) => getType(type));
39
+ return joinedTypes
40
+ .reduce((acc, type) => `${acc} ${joinChar} ${type}`, "")
41
+ .slice(2);
42
+ }
43
+
44
+ /** Return the type of a reflection.
45
+ * For anything that has, or can have, multiple subtypes (i.e. variable types in a generic, properties in an interface,
46
+ * several types in a union, callbacks, etc.) it will recursively navigate the parsed type info as needed to resolve
47
+ * all relevant subtypes.
48
+ */
49
+ function getType(reflection) {
50
+ switch (reflection.type) {
51
+ case "intrinsic":
52
+ case "reference":
53
+ return reflection.name + getVariableType(reflection.typeArguments);
54
+ case "union":
55
+ return getJoinedTypes(reflection.types, "|");
56
+ case "reflection":
57
+ const { signatures, children } = reflection.declaration;
58
+ if (signatures) {
59
+ return getFunctionDocumentation(signatures[0]).type;
60
+ } else if (children) {
61
+ return getPropertyTypes(children);
62
+ } else {
63
+ return "Props";
64
+ }
65
+ case "array":
66
+ return reflection.elementType.name + "[]";
67
+ case "tuple":
68
+ return getTupleTypes(reflection.elements);
69
+ case "intersection":
70
+ return getJoinedTypes(reflection.types, "&");
71
+ case "literal":
72
+ return reflection.value;
73
+ }
74
+ }
75
+
76
+ /** Compiles information about the parameters of a function.
77
+ * Includes the name, default value, type, and whether it is optional.
78
+ */
79
+ function getParamInfo(parameters = []) {
80
+ return parameters.map((parameter) => {
81
+ const { name, defaultValue, type, flags } = parameter;
82
+ return {
83
+ name,
84
+ default: defaultValue,
85
+ type: getType(type),
86
+ optional: flags.isOptional,
87
+ };
88
+ });
89
+ }
90
+
91
+ /** Formats call signature for a function. */
92
+ function formatFunctionType(parameters, returnType) {
93
+ const annotatedParams = parameters.map((parameter) => {
94
+ const { name, type, optional } = parameter;
95
+
96
+ return [optional ? name + "?" : name, type];
97
+ });
98
+
99
+ const formattedParams = annotatedParams
100
+ .reduce((acc, param) => `${acc}, ${param[0]}: ${param[1]}`, "")
101
+ .slice(2);
102
+
103
+ return `(${formattedParams}) => ${returnType}`;
104
+ }
105
+
106
+ /** Primary entry point for gathering type information from a typedoc function reflection. */
107
+ function getFunctionDocumentation(callSignatureReflection) {
108
+ const { type, parameters, comment } = callSignatureReflection;
109
+ const params = getParamInfo(parameters);
110
+
111
+ const returnType = type?.name || getType(type);
112
+
113
+ return {
114
+ params,
115
+ returnType,
116
+ type: formatFunctionType(params, returnType),
117
+ description: comment?.shortText,
118
+ };
119
+ }
120
+
121
+ /** Parses the source for a package using TypeDoc. */
122
+ function typeDocGen(entryPoint, tsconfigLocation) {
123
+ const app = new TypeDoc.Application();
124
+ app.options.addReader(new TypeDoc.TSConfigReader());
125
+ app.bootstrap({
126
+ // typedoc options here
127
+ entryPointStrategy: "expand",
128
+ entryPoints: [entryPoint],
129
+ tsconfig: tsconfigLocation,
130
+ });
131
+
132
+ // this non-standard reflection creation allows us to ignore any type errors in a package
133
+ const project = app.converter.convert(app.getEntryPoints() ?? []);
134
+
135
+ // if something caused project conversion to fail log an error
136
+ if (project) {
137
+ return project;
138
+ } else {
139
+ console.error("Something went wrong during typedoc project conversion");
140
+ return {};
141
+ }
142
+ }
143
+
144
+ /** Takes package information and returns an object with all tsdoc standard format info about the functions in it.
145
+ *
146
+ * The object has file names as keys, with values being an additional object which has the function names in that file
147
+ * as keys and the information about that function as the value, also in object form.
148
+ * Information includes the name of the file in which it's defined, the parameters, description, default values and
149
+ * type information.
150
+ *
151
+ * Example structure:
152
+ * {
153
+ * "components/component.tsx": {
154
+ * "boolToString": {
155
+ * "description": "Converts a boolean to a string",
156
+ * "params": [
157
+ * {
158
+ * "default": false,
159
+ * "name": "booleanValue",
160
+ * "optional": true,
161
+ * "type": "boolean",
162
+ * },
163
+ * ],
164
+ * "returnType": "string",
165
+ * "type": "(booleanValue?: boolean) => string",
166
+ * },
167
+ * },
168
+ * }
169
+ */
170
+ function getPackageFunctionDocumentation(
171
+ packageName,
172
+ pathToRoot = "dist/js/index.js",
173
+ srcPath = "src",
174
+ tsconfigPath = "tsconfig.json"
175
+ ) {
176
+ const packageRoot = require.resolve(packageName).replace(pathToRoot, "");
177
+ const entry = path.relative(process.cwd(), path.join(packageRoot, srcPath));
178
+ const configLocation = path.relative(
179
+ process.cwd(),
180
+ path.join(packageRoot, tsconfigPath)
181
+ );
182
+
183
+ const packageReflection = typeDocGen(entry, configLocation);
184
+
185
+ // 64 corresponds with functions, see all reflection kinds here: https://typedoc.org/api/enums/Models.ReflectionKind-1.html
186
+ const functionReflections = packageReflection.getReflectionsByKind(64);
187
+
188
+ const functionsMap = functionReflections.reduce((acc, functionReflection) => {
189
+ const { name, sources, signatures } = functionReflection;
190
+
191
+ const sourceFile = sources[0].fileName;
192
+ const shortSourceFile = sourceFile.replace(
193
+ `${packageName}/${srcPath}/`,
194
+ ""
195
+ );
196
+ const obj = getFunctionDocumentation(signatures[0]);
197
+
198
+ if (acc[shortSourceFile]) {
199
+ acc[shortSourceFile] = { ...acc[shortSourceFile], [name]: obj };
200
+ } else {
201
+ acc[shortSourceFile] = { [name]: obj };
202
+ }
203
+ return acc;
204
+ }, {});
205
+
206
+ return functionsMap;
207
+ }
208
+
209
+ module.exports = { getPackageFunctionDocumentation };
@@ -8,6 +8,7 @@ module.exports = (_env, argv) => {
8
8
  const {
9
9
  pathPrefix = '',
10
10
  mode,
11
+ googleAnalyticsID = false,
11
12
  algolia = {},
12
13
  hasGdprBanner = false,
13
14
  hasFooter = false,
@@ -27,7 +28,8 @@ module.exports = (_env, argv) => {
27
28
  output: {
28
29
  publicPath: isProd ? `${pathPrefix}/` : '/',
29
30
  pathinfo: false, // https://webpack.js.org/guides/build-performance/#output-without-path-info,
30
- hashDigestLength: 8
31
+ hashDigestLength: 8,
32
+ clean: true, // Clean the output directory before emit.
31
33
  },
32
34
  amd: false, // We don't use any AMD modules, helps performance
33
35
  mode: isProd ? 'production' : 'development',
@@ -39,9 +41,12 @@ module.exports = (_env, argv) => {
39
41
  include: [
40
42
  path.resolve(process.cwd(), 'src'),
41
43
  path.resolve(process.cwd(), 'patternfly-docs'),
44
+ path.resolve(process.cwd(), 'examples'),
42
45
  path.resolve(__dirname, '../..'), // Temporarily compile theme using webpack for development
43
46
  /react-[\w-]+\/src\/.*\/examples/,
44
47
  /react-[\w-]+\\src\\.*\\examples/, // fix for Windows
48
+ /react-[\w-]+\/patternfly-docs\/.*\/examples/, //fixes for extensions
49
+ /react-[\w-]+\\patternfly-docs\\.*\\examples/,
45
50
  ].concat(includePaths.map(path => new RegExp(path))),
46
51
  exclude: [
47
52
  path.resolve(__dirname, '../../node_modules'), // Temporarily compile theme using webpack for development
@@ -82,35 +87,28 @@ module.exports = (_env, argv) => {
82
87
  },
83
88
  {
84
89
  test: /\.(gif|svg)$/,
85
- use: {
86
- loader: 'file-loader',
87
- options: {
88
- name: '[name].[contenthash].[ext]',
89
- outputPath: 'images/'
90
- },
90
+ type: 'asset/resource',
91
+ dependency: { not: ['url'] },
92
+ generator: {
93
+ filename: 'images/[hash][ext][query]'
91
94
  }
92
95
  },
93
96
  {
94
97
  test: /\.(pdf)$/,
95
- use: {
96
- loader: 'file-loader',
97
- options: {
98
- name: '[name].[contenthash].[ext]',
99
- }
98
+ type: 'asset/resource',
99
+ dependency: { not: ['url'] },
100
+ generator: {
101
+ filename: '[hash][ext][query]'
100
102
  }
101
103
  },
102
104
  {
103
105
  test: /.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
104
- use: [
105
- {
106
- loader: 'file-loader',
107
- options: {
108
- name: '[name].[ext]',
109
- outputPath: 'fonts/'
110
- }
111
- }
112
- ]
113
- }
106
+ type: 'asset/resource',
107
+ dependency: { not: ['url'] },
108
+ generator: {
109
+ filename: 'fonts/[name][ext][query]'
110
+ }
111
+ },
114
112
  ]
115
113
  },
116
114
  resolve: {
@@ -118,21 +116,29 @@ module.exports = (_env, argv) => {
118
116
  alias: {
119
117
  'client-styles': path.resolve(process.cwd(), 'patternfly-docs/patternfly-docs.css.js'),
120
118
  './routes-client': path.resolve(process.cwd(), 'patternfly-docs/patternfly-docs.routes.js'),
121
- './routes-generated': path.resolve(process.cwd(), 'patternfly-docs/generated/index.js')
119
+ './routes-generated': path.resolve(process.cwd(), 'patternfly-docs/generated/index.js'),
120
+ process: "process/browser"
122
121
  },
123
122
  modules: [
124
123
  'node_modules',
125
124
  ...module.paths,
126
- ]
125
+ ],
126
+ fallback: {
127
+ "path": require.resolve("path-browserify")
128
+ },
127
129
  },
128
130
  // Use this module's node_modules first (for use in Core/React workspaces)
129
131
  resolveLoader: {
130
132
  modules: module.paths,
131
133
  },
132
134
  plugins: [
135
+ new webpack.ProvidePlugin({
136
+ process: 'process/browser',
137
+ }),
133
138
  new webpack.DefinePlugin({
134
139
  'process.env.NODE_ENV': JSON.stringify(mode),
135
140
  'process.env.pathPrefix': JSON.stringify(isProd ? pathPrefix : ''),
141
+ 'process.env.googleAnalyticsID': JSON.stringify(isProd ? googleAnalyticsID : ''),
136
142
  'process.env.algolia': JSON.stringify(algolia),
137
143
  'process.env.hasGdprBanner': JSON.stringify(hasGdprBanner),
138
144
  'process.env.hasFooter': JSON.stringify(hasFooter),
@@ -143,20 +149,16 @@ module.exports = (_env, argv) => {
143
149
  'process.env.sideNavItems': JSON.stringify(sideNavItems),
144
150
  'process.env.topNavItems': JSON.stringify(topNavItems),
145
151
  'process.env.prnum': JSON.stringify(process.env.CIRCLE_PR_NUMBER || process.env.PR_NUMBER || ''),
146
- 'process.env.prurl': JSON.stringify(process.env.CIRCLE_PULL_REQUEST || ''),
152
+ 'process.env.prurl': JSON.stringify(process.env.CIRCLE_PULL_REQUEST || '')
147
153
  }),
148
154
  new CopyWebpackPlugin({
149
155
  patterns: [
150
156
  { from: path.join(__dirname, '../../assets'), to: 'assets' }
151
157
  ]
152
158
  }),
153
- new MonacoWebpackPlugin(),
154
- ...(isProd
155
- ? [
156
- new CleanWebpackPlugin()
157
- ]
158
- : []
159
- )
159
+ new MonacoWebpackPlugin({
160
+ globalAPI: true,
161
+ })
160
162
  ],
161
163
  stats: 'minimal'
162
164
  };
@@ -5,6 +5,7 @@ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPl
5
5
  const MiniCssExtractPlugin = require('mini-css-extract-plugin');
6
6
  const TerserPlugin = require('terser-webpack-plugin');
7
7
  const CopyPlugin = require('copy-webpack-plugin');
8
+ const webpack = require('webpack');
8
9
  const baseConfig = require('./webpack.base.config');
9
10
  const { getHtmlWebpackPlugins } = require('./getHtmlWebpackPlugins');
10
11
 
@@ -23,18 +24,20 @@ const reactJSRegex = /react-([^\\/]*)[\\/]dist[\\/].*\.js$/
23
24
 
24
25
  const clientConfig = async (env, argv) => {
25
26
  const isProd = argv.mode === 'production';
26
-
27
27
  return {
28
28
  output: {
29
29
  path: argv.output ? path.resolve(argv.output) : path.resolve('public'),
30
- filename: '[name].[hash].bundle.js'
30
+ filename: '[name].[contenthash].bundle.js'
31
31
  },
32
32
  devServer: {
33
33
  hot: true,
34
34
  historyApiFallback: true,
35
+ compress: true,
35
36
  port: argv.port,
36
- clientLogLevel: 'info',
37
- stats: 'minimal'
37
+ client: {
38
+ logging: 'info',
39
+ },
40
+ static: {}
38
41
  },
39
42
  optimization: {
40
43
  splitChunks: {
@@ -71,10 +74,7 @@ const clientConfig = async (env, argv) => {
71
74
  },
72
75
  minimize: isProd ? true : false,
73
76
  minimizer: [
74
- new TerserPlugin({
75
- cache: path.join(process.cwd(), '.cache/terser'),
76
- ...(process.env.CI ? { parallel: 2 } : {})
77
- }),
77
+ new TerserPlugin(),
78
78
  ],
79
79
  runtimeChunk: 'single',
80
80
  },
@@ -113,6 +113,9 @@ const clientConfig = async (env, argv) => {
113
113
  ]
114
114
  },
115
115
  plugins: [
116
+ new webpack.DefinePlugin({
117
+ 'process.env.PRERENDER': false,
118
+ }),
116
119
  new MiniCssExtractPlugin(!isProd ? {} : {
117
120
  filename: '[name].[contenthash].css',
118
121
  chunkFilename: '[name].[contenthash].css',