@linktr.ee/create-link-app 2.0.0 → 2.2.0
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.
- package/README.md +8 -22
- package/dist/commands/build.js +80 -3
- package/dist/commands/create.js +9 -13
- package/dist/commands/deploy.js +16 -15
- package/dist/commands/dev.js +3 -0
- package/dist/commands/grant-access.js +3 -2
- package/dist/commands/login.js +8 -7
- package/dist/commands/logout.js +3 -2
- package/dist/commands/storybook.js +3 -1
- package/dist/commands/test-url-match-rules.js +4 -0
- package/dist/lib/create/create-project.js +2 -2
- package/dist/webpack/development.entry.js +19 -43
- package/dist/webpack/webpack.config.js +141 -3
- package/html-template/development.html +2 -2
- package/html-template/production.html +2 -2
- package/oclif.manifest.json +9 -27
- package/package.json +2 -1
- package/templates/common/url_match_rules.json +10 -0
- package/templates/react-ts/package.json +1 -1
- package/templates/react-ts/postcss.config.js +2 -2
- package/templates/react-ts/tailwind.config.js +2 -2
- package/dist/commands/generate-types.js +0 -102
- package/dist/webpack/simulator.js +0 -373
- package/templates/react/package.json +0 -16
- package/templates/react/src/index.jsx +0 -12
- package/templates/react/src/tailwind.css +0 -5
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
3
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
4
|
};
|
|
@@ -46,17 +45,46 @@ async function default_1(env, options) {
|
|
|
46
45
|
const linkTypeSlug = (0, slugify_1.default)(linkTypeName, { lower: true });
|
|
47
46
|
const linkTypeId = (0, camelcase_1.default)(linkTypeSlug, { pascalCase: true });
|
|
48
47
|
const hasTsconfig = fileExists(path_1.default.resolve(appDir, 'tsconfig.json'));
|
|
48
|
+
// Check if we should enable profiling and analysis
|
|
49
|
+
const enableProfiling = options?.profile || false;
|
|
49
50
|
const config = {
|
|
50
51
|
target: 'web',
|
|
51
52
|
mode: env,
|
|
52
53
|
entry: entryFile,
|
|
54
|
+
// Enable webpack persistent caching for faster subsequent builds
|
|
55
|
+
cache: env === 'production'
|
|
56
|
+
? {
|
|
57
|
+
type: 'filesystem',
|
|
58
|
+
buildDependencies: {
|
|
59
|
+
config: [__filename],
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
: undefined,
|
|
53
63
|
output: {
|
|
54
64
|
publicPath: 'auto',
|
|
55
65
|
path: path_1.default.resolve(appDir, 'dist'),
|
|
56
66
|
assetModuleFilename: 'images/[hash].[contenthash][ext][query]',
|
|
57
67
|
chunkFilename: '[id].[contenthash].js',
|
|
58
68
|
filename: '[name].[contenthash].js',
|
|
69
|
+
// Clean dist folder before each build
|
|
70
|
+
clean: true,
|
|
59
71
|
},
|
|
72
|
+
// Enable profiling for production builds when requested
|
|
73
|
+
...(enableProfiling && {
|
|
74
|
+
profile: true,
|
|
75
|
+
stats: {
|
|
76
|
+
timings: true,
|
|
77
|
+
modules: true,
|
|
78
|
+
moduleTrace: true,
|
|
79
|
+
reasons: true,
|
|
80
|
+
usedExports: true,
|
|
81
|
+
providedExports: true,
|
|
82
|
+
optimizationBailout: true,
|
|
83
|
+
errorDetails: true,
|
|
84
|
+
logging: 'verbose',
|
|
85
|
+
loggingTrace: true,
|
|
86
|
+
},
|
|
87
|
+
}),
|
|
60
88
|
module: {
|
|
61
89
|
rules: [
|
|
62
90
|
{
|
|
@@ -70,11 +98,19 @@ async function default_1(env, options) {
|
|
|
70
98
|
[require.resolve('@babel/preset-react'), { runtime: 'automatic' }],
|
|
71
99
|
],
|
|
72
100
|
plugins: [require.resolve('@babel/plugin-transform-runtime')],
|
|
101
|
+
// Enable caching for faster rebuilds
|
|
102
|
+
cacheDirectory: true,
|
|
103
|
+
cacheCompression: false, // Don't compress cache files for faster access
|
|
73
104
|
},
|
|
74
105
|
},
|
|
75
106
|
{
|
|
76
107
|
test: /\.(png|jpe?g|gif|svg)$/i,
|
|
77
|
-
type: 'asset
|
|
108
|
+
type: 'asset',
|
|
109
|
+
parser: {
|
|
110
|
+
dataUrlCondition: {
|
|
111
|
+
maxSize: 8 * 1024, // Only inline images smaller than 8KB
|
|
112
|
+
},
|
|
113
|
+
},
|
|
78
114
|
},
|
|
79
115
|
{
|
|
80
116
|
test: /\.css$/,
|
|
@@ -111,19 +147,36 @@ async function default_1(env, options) {
|
|
|
111
147
|
new html_webpack_plugin_1.default({
|
|
112
148
|
template: htmlTemplateFile,
|
|
113
149
|
excludeChunks: [`LinkApp_${linkTypeId}`],
|
|
150
|
+
templateParameters: {
|
|
151
|
+
linkTypeSlug: linkTypeSlug,
|
|
152
|
+
},
|
|
153
|
+
}),
|
|
154
|
+
// Add progress plugin for better build feedback
|
|
155
|
+
new webpack_1.ProgressPlugin({
|
|
156
|
+
activeModules: true,
|
|
157
|
+
entries: true,
|
|
158
|
+
modules: true,
|
|
159
|
+
modulesCount: 5000,
|
|
160
|
+
profile: enableProfiling,
|
|
161
|
+
dependencies: true,
|
|
162
|
+
dependenciesCount: 10000,
|
|
163
|
+
percentBy: 'entries',
|
|
114
164
|
}),
|
|
115
165
|
],
|
|
116
166
|
};
|
|
117
167
|
// Type checking on a separate process - @babel/preset-typescript only handles transpilation
|
|
118
168
|
if (hasTsconfig) {
|
|
169
|
+
config.plugins = config.plugins || [];
|
|
119
170
|
config.plugins.push(new fork_ts_checker_webpack_plugin_1.default());
|
|
120
171
|
}
|
|
121
172
|
if (env === 'development') {
|
|
122
173
|
config.devtool = 'cheap-module-source-map';
|
|
174
|
+
config.resolve = config.resolve || {};
|
|
123
175
|
config.resolve.alias = {
|
|
124
176
|
...config.resolve.alias,
|
|
125
177
|
'@linktr.ee/extension-dev-data': path_1.default.resolve(appDir, 'fixtures', 'props-data.json'),
|
|
126
178
|
};
|
|
179
|
+
config.plugins = config.plugins || [];
|
|
127
180
|
config.plugins.push(new mini_css_extract_plugin_1.default({
|
|
128
181
|
filename: '[name].[contenthash].css',
|
|
129
182
|
chunkFilename: '[id].[contenthash].css',
|
|
@@ -142,6 +195,91 @@ async function default_1(env, options) {
|
|
|
142
195
|
if (useSheetEntry) {
|
|
143
196
|
exposedEntryPoints['./Sheet'] = path_1.default.resolve(appDir, 'src/Sheet');
|
|
144
197
|
}
|
|
198
|
+
// Add bundle analyzer if requested
|
|
199
|
+
if (enableProfiling) {
|
|
200
|
+
try {
|
|
201
|
+
// Dynamically import webpack-bundle-analyzer to avoid requiring it as a hard dependency
|
|
202
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-explicit-any
|
|
203
|
+
const bundleAnalyzer = require('webpack-bundle-analyzer');
|
|
204
|
+
const BundleAnalyzerPlugin = bundleAnalyzer.BundleAnalyzerPlugin;
|
|
205
|
+
config.plugins?.push(new BundleAnalyzerPlugin({
|
|
206
|
+
analyzerMode: 'static',
|
|
207
|
+
reportFilename: path_1.default.resolve(appDir, 'dist', 'bundle-report.html'),
|
|
208
|
+
openAnalyzer: false,
|
|
209
|
+
generateStatsFile: true,
|
|
210
|
+
statsFilename: path_1.default.resolve(appDir, 'dist', 'webpack-stats.json'),
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
console.warn('⚠️ webpack-bundle-analyzer not installed. Run: npm install --save-dev webpack-bundle-analyzer');
|
|
215
|
+
console.warn(' Bundle analysis will be skipped.');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Optimize build performance and bundle splitting
|
|
219
|
+
config.optimization = {
|
|
220
|
+
minimize: true,
|
|
221
|
+
minimizer: [
|
|
222
|
+
// Configure TerserPlugin for better performance
|
|
223
|
+
'...',
|
|
224
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
225
|
+
new (require('terser-webpack-plugin'))({
|
|
226
|
+
parallel: true,
|
|
227
|
+
terserOptions: {
|
|
228
|
+
compress: {
|
|
229
|
+
// Reduce compression passes for faster builds
|
|
230
|
+
passes: 1,
|
|
231
|
+
drop_console: true,
|
|
232
|
+
drop_debugger: true,
|
|
233
|
+
},
|
|
234
|
+
mangle: {
|
|
235
|
+
safari10: true, // Fix Safari 10+ bug
|
|
236
|
+
},
|
|
237
|
+
format: {
|
|
238
|
+
comments: false, // Remove all comments
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
extractComments: false, // Don't create separate LICENSE files
|
|
242
|
+
}),
|
|
243
|
+
],
|
|
244
|
+
splitChunks: {
|
|
245
|
+
chunks: 'all',
|
|
246
|
+
cacheGroups: {
|
|
247
|
+
// Separate vendor libraries for better caching
|
|
248
|
+
vendor: {
|
|
249
|
+
test: /[\\/]node_modules[\\/]/,
|
|
250
|
+
name: 'vendors',
|
|
251
|
+
chunks: 'all',
|
|
252
|
+
priority: 10,
|
|
253
|
+
},
|
|
254
|
+
// Separate large UI library
|
|
255
|
+
uiKit: {
|
|
256
|
+
test: /[\\/]node_modules[\\/]@linktr\.ee[\\/]ui-link-kit[\\/]/,
|
|
257
|
+
name: 'ui-kit',
|
|
258
|
+
chunks: 'all',
|
|
259
|
+
priority: 20,
|
|
260
|
+
},
|
|
261
|
+
// Separate icon libraries
|
|
262
|
+
icons: {
|
|
263
|
+
test: /[\\/]node_modules[\\/].*icons.*[\\/]/,
|
|
264
|
+
name: 'icons',
|
|
265
|
+
chunks: 'all',
|
|
266
|
+
priority: 15,
|
|
267
|
+
},
|
|
268
|
+
// Common code shared between chunks
|
|
269
|
+
common: {
|
|
270
|
+
name: 'common',
|
|
271
|
+
minChunks: 2,
|
|
272
|
+
chunks: 'all',
|
|
273
|
+
priority: 5,
|
|
274
|
+
reuseExistingChunk: true,
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
// Enable runtime chunk for better caching
|
|
279
|
+
runtimeChunk: {
|
|
280
|
+
name: 'runtime',
|
|
281
|
+
},
|
|
282
|
+
};
|
|
145
283
|
// TODO: Figure out how to manage externals with Module Federation
|
|
146
284
|
// Possibly make the index.html a host app, via separate webpack config
|
|
147
285
|
// config.externals = {
|
|
@@ -154,7 +292,7 @@ async function default_1(env, options) {
|
|
|
154
292
|
maxAssetSize: 350000,
|
|
155
293
|
hints: 'warning',
|
|
156
294
|
};
|
|
157
|
-
config.plugins
|
|
295
|
+
config.plugins?.push(new webpack_1.DefinePlugin({
|
|
158
296
|
__ALLOW_ANY_ORIGIN__: options?.allowAnyOrigin,
|
|
159
297
|
__LINK_TYPE_SLUG__: JSON.stringify(linkTypeSlug),
|
|
160
298
|
__LINK_TYPE_ID__: JSON.stringify(linkTypeId),
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.2.0",
|
|
3
3
|
"commands": {
|
|
4
4
|
"build": {
|
|
5
5
|
"id": "build",
|
|
@@ -23,6 +23,12 @@
|
|
|
23
23
|
"type": "boolean",
|
|
24
24
|
"description": "Build native components of a Link App ready for publishing to npm",
|
|
25
25
|
"allowNo": false
|
|
26
|
+
},
|
|
27
|
+
"profile": {
|
|
28
|
+
"name": "profile",
|
|
29
|
+
"type": "boolean",
|
|
30
|
+
"description": "Enable detailed webpack profiling and bundle analysis",
|
|
31
|
+
"allowNo": false
|
|
26
32
|
}
|
|
27
33
|
},
|
|
28
34
|
"args": {}
|
|
@@ -38,22 +44,10 @@
|
|
|
38
44
|
"hiddenAliases": [],
|
|
39
45
|
"examples": [
|
|
40
46
|
"$ create-link-app create my-link-app",
|
|
41
|
-
"$ create-link-app create my-link-app --
|
|
42
|
-
"$ create-link-app create my-link-app --
|
|
47
|
+
"$ create-link-app create my-link-app --path my/custom/path",
|
|
48
|
+
"$ create-link-app create my-link-app --storybook"
|
|
43
49
|
],
|
|
44
50
|
"flags": {
|
|
45
|
-
"template": {
|
|
46
|
-
"name": "template",
|
|
47
|
-
"type": "option",
|
|
48
|
-
"char": "t",
|
|
49
|
-
"description": "Template to use for the project",
|
|
50
|
-
"multiple": false,
|
|
51
|
-
"options": [
|
|
52
|
-
"react",
|
|
53
|
-
"react-ts"
|
|
54
|
-
],
|
|
55
|
-
"default": "react-ts"
|
|
56
|
-
},
|
|
57
51
|
"path": {
|
|
58
52
|
"name": "path",
|
|
59
53
|
"type": "option",
|
|
@@ -176,18 +170,6 @@
|
|
|
176
170
|
},
|
|
177
171
|
"args": {}
|
|
178
172
|
},
|
|
179
|
-
"generate-types": {
|
|
180
|
-
"id": "generate-types",
|
|
181
|
-
"description": "Generate Typescript types from the schema definitions",
|
|
182
|
-
"strict": true,
|
|
183
|
-
"pluginName": "@linktr.ee/create-link-app",
|
|
184
|
-
"pluginAlias": "@linktr.ee/create-link-app",
|
|
185
|
-
"pluginType": "core",
|
|
186
|
-
"aliases": [],
|
|
187
|
-
"hiddenAliases": [],
|
|
188
|
-
"flags": {},
|
|
189
|
-
"args": {}
|
|
190
|
-
},
|
|
191
173
|
"grant-access": {
|
|
192
174
|
"id": "grant-access",
|
|
193
175
|
"description": "Grant access to other developers to push updates for your Link App",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linktr.ee/create-link-app",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Create a Link App on Linktr.ee.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Linktree",
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
"style-loader": "^3.3.2",
|
|
77
77
|
"styled-components": "^5.3.5",
|
|
78
78
|
"tailwindcss": "^3.3.2",
|
|
79
|
+
"terser-webpack-plugin": "^5.3.10",
|
|
79
80
|
"ts-loader": "^9.4.4",
|
|
80
81
|
"typescript": "^4.7.3",
|
|
81
82
|
"webpack": "^5.75.0",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"build": "create-link-app build",
|
|
5
5
|
"login-app": "create-link-app login",
|
|
6
6
|
"logout-app": "create-link-app logout",
|
|
7
|
-
"
|
|
7
|
+
"deploy": "create-link-app deploy",
|
|
8
8
|
"dev": "create-link-app dev",
|
|
9
9
|
"prepack": "create-link-app build --native",
|
|
10
10
|
"test-url-match-rules": "create-link-app test-url-match-rules"
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const path_1 = __importDefault(require("path"));
|
|
7
|
-
const base_1 = __importDefault(require("../base"));
|
|
8
|
-
const child_process_1 = require("child_process");
|
|
9
|
-
class MissingDependencyException extends Error {
|
|
10
|
-
constructor(packageName) {
|
|
11
|
-
super(`'${packageName}' is required on your system. Please refer to the create-link-app README`);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
const ucfirst = (str) => {
|
|
15
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
16
|
-
};
|
|
17
|
-
class GenerateTypes extends base_1.default {
|
|
18
|
-
constructor() {
|
|
19
|
-
super(...arguments);
|
|
20
|
-
this.schemaDirPath = path_1.default.join(process.cwd(), '/schema');
|
|
21
|
-
this.tmpPath = path_1.default.join(process.cwd(), '/__temp__');
|
|
22
|
-
this.typesPath = path_1.default.join(process.cwd(), '/src/types/schema');
|
|
23
|
-
}
|
|
24
|
-
async run() {
|
|
25
|
-
try {
|
|
26
|
-
// Check for necessary deps
|
|
27
|
-
await this.dependOn('npx');
|
|
28
|
-
await this.dependOn('jtd-codegen');
|
|
29
|
-
await this.log('✓ All dependencies present');
|
|
30
|
-
// Ensure necessary directories exist
|
|
31
|
-
await this.cmd(`mkdir -p ${this.tmpPath} && touch ${this.tmpPath}/index.ts`);
|
|
32
|
-
await this.cmd(`mkdir -p ${this.typesPath} && touch ${this.typesPath}/index.ts`);
|
|
33
|
-
await this.log('✓ Files prepped for generation');
|
|
34
|
-
// Wipe existing types & drop comments
|
|
35
|
-
await this.cmd(`> ${this.typesPath}/index.ts`);
|
|
36
|
-
await this.cmd(`echo "/**" >> ${this.typesPath}/index.ts`);
|
|
37
|
-
await this.cmd(`echo " * These types were autogenerated by @linktr.ee/create-link-app" >> ${this.typesPath}/index.ts`);
|
|
38
|
-
await this.cmd(`echo " * https://www.npmjs.com/package/@linktr.ee/create-link-app " >> ${this.typesPath}/index.ts`);
|
|
39
|
-
await this.cmd(`echo " */" >> ${this.typesPath}/index.ts`);
|
|
40
|
-
// Clean up file formatting
|
|
41
|
-
await this.cmd(`npx prettier ${this.typesPath}/index.ts --write`);
|
|
42
|
-
await this.log('✓ All types created successfully');
|
|
43
|
-
// Garbage collect temporary dir
|
|
44
|
-
await this.cmd(`rm -rf ${this.tmpPath}`);
|
|
45
|
-
await this.log('✓ Cleanup complete');
|
|
46
|
-
}
|
|
47
|
-
catch (e) {
|
|
48
|
-
await this.log(`𐄂 ERROR: ${e}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Generates a Typescript type for the schema defined in schema/<schemaName>.jtd.json
|
|
53
|
-
* and appends that type to src/types/schema/index.ts
|
|
54
|
-
*/
|
|
55
|
-
async generateAndAppendSchemaType(schemaName) {
|
|
56
|
-
// Generate schema
|
|
57
|
-
await this.cmd(`jtd-codegen ${this.schemaDirPath}/${schemaName}.jtd.json --typescript-out ${this.tmpPath} --root-name=${ucfirst(schemaName)}Data`);
|
|
58
|
-
// Strip jtd comment
|
|
59
|
-
await this.cmd(`sed '/^\\/\\//d' ${this.tmpPath}/index.ts > ${this.tmpPath}/parsed.ts`);
|
|
60
|
-
// Append to final file
|
|
61
|
-
await this.cmd(`cat ${this.tmpPath}/parsed.ts >> ${this.typesPath}/index.ts`);
|
|
62
|
-
}
|
|
63
|
-
async dependOn(dependencyName) {
|
|
64
|
-
try {
|
|
65
|
-
await this.cmd(`command -v ${dependencyName} || exit 1`);
|
|
66
|
-
}
|
|
67
|
-
catch (e) {
|
|
68
|
-
throw new MissingDependencyException('prettier');
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Run a command with spawn effectively synchronously
|
|
73
|
-
*/
|
|
74
|
-
async cmd(command, opts = {
|
|
75
|
-
shell: true,
|
|
76
|
-
stdio: 'ignore',
|
|
77
|
-
}, onError) {
|
|
78
|
-
await new Promise((resolve, reject) => {
|
|
79
|
-
(0, child_process_1.spawn)(command, opts)
|
|
80
|
-
.on('error', (e) => {
|
|
81
|
-
reject(e);
|
|
82
|
-
})
|
|
83
|
-
.on('exit', (code) => {
|
|
84
|
-
if (code === 1)
|
|
85
|
-
reject({ exitCode: code });
|
|
86
|
-
})
|
|
87
|
-
.on('close', () => {
|
|
88
|
-
resolve();
|
|
89
|
-
});
|
|
90
|
-
}).catch((e) => {
|
|
91
|
-
if (onError) {
|
|
92
|
-
onError();
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
throw e;
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
exports.default = GenerateTypes;
|
|
102
|
-
GenerateTypes.description = 'Generate Typescript types from the schema definitions';
|