Skip to content

Commit 270c1b2

Browse files
committed
feat: chalk up the cli
Now we are ready to test through some docker container.
1 parent 3e74066 commit 270c1b2

File tree

5 files changed

+292
-23
lines changed

5 files changed

+292
-23
lines changed

.vscode/settings.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,10 @@
1111
"editor.formatOnSave": true
1212
},
1313
"flow.useLSP": true,
14-
"typescript.tsdk": "node_modules/typescript/lib"
14+
"typescript.tsdk": "node_modules/typescript/lib",
15+
"cSpell.words": [
16+
"Packio",
17+
"uglifyjs",
18+
"wpack"
19+
]
1520
}

packages/scripts/PREFACE.md

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,62 @@
55
- DO NOT RELY ON `process.env.NODE_ENV`. Rather set it automatically depending on cli commands.
66
- `start` - Start browsersync sever with webpack middleware.
77
- `build` - Compile files.
8-
- `init` - Create a `wpackio.server.js` through asking some questions (only if the file is not present).
8+
- `init` - Create a `wpackio.server.json` through asking some questions (only if the file is not present).
99
- Also set `process.env.BABEL_ENV` so that `babel-loader` can play nice, (especially with the preset-react).
1010

11-
## Structure `wpackio.project.js`
11+
## For the PHP Script
12+
13+
We will need to feed it the outputPath to keep things fast and not have it load the project.js
14+
file.
15+
16+
```php
17+
<?php
18+
19+
$enqueue = new \WPackio\Enqueue( $plugin_path, $output_path );
20+
$enqueue->enqueue( 'entry_name' );
21+
$enqueue->enqueue( 'entry_name', 'chunk_name' );
22+
$enqueue->enqueue( 'entry_name', 'chunk_name', [
23+
'other' => 'localization',
24+
] );
25+
```
26+
27+
## Structure `wpackio.project.json`
1228

1329
```js
1430
module.exports = {
31+
// Project Identity
32+
type: 'plugin', // Plugin or theme
33+
slug: 'wpack-io', // Plugin or Theme slug, basically the directory name under `wp-content/<themes|plugins>`
34+
// Used to generate banners on top of compiled stuff
35+
bannerConfig: {
36+
name: 'WordPress WebPack Bundler',
37+
author: 'Swashata Ghosh',
38+
license: 'GPL-3.0',
39+
link: 'https://wpack.io',
40+
version: '1.0.0',
41+
copyrightText:
42+
'This software is released under the GPL-3.0 License\nhttps://opensource.org/licenses/GPL-3.0',
43+
credit: true,
44+
},
1545
// Files we need to compile, and where to put
1646
files: [
1747
// If this has length === 1, then single compiler
1848
{
49+
name: 'mobile',
1950
entry: {
2051
// stuff
52+
vendor: 'vendor.js',
53+
main: ['src/mobile.js'],
2154
},
2255
filename: '[name].js',
23-
path: path.resolve(__dirname, 'dist'),
56+
// Extra webpack config to be passed directly
57+
webpackConfig: undefined,
2458
},
2559
// If has more length, then multi-compiler
2660
],
61+
// Output path relative to the context directory
62+
// We need relative path here, else, we can not map to publicPath
63+
outputPath: 'dist',
2764
// Project specific config
2865
// Needs react?
2966
hasReact: true,
@@ -33,15 +70,17 @@ module.exports = {
3370
externals: {
3471
jquery: 'jQuery',
3572
},
73+
// Webpack Aliases
74+
alias: undefined,
3675
// Show overlay on development
3776
errorOverlay: true,
3877
// Auto optimization by webpack
3978
// Split all common chunks with default config
4079
// <https://webpack.js.org/plugins/split-chunks-plugin/#optimization-splitchunks>
4180
// Won't hurt because we use PHP to automate loading
4281
optimizeSplitChunks: true,
43-
// Extra webpack config to be passed directly
44-
webpackConfig: false,
82+
// Usually PHP and other files to watch and reload when changed
83+
watch: 'inc/**/*.php',
4584
};
4685
```
4786

@@ -53,7 +92,7 @@ Possible `package.json`
5392
{
5493
"name": "@wpackio/scripts",
5594
"version": "0.0.0",
56-
"description": "@wpackios/scripts is a single dependency for using WordPress webpack script.",
95+
"description": "@wpackio/scripts is a single dependency for using WordPress webpack script.",
5796
"main": "index.js",
5897
"repository": "https://github.com/swashata/wp-webpack-script",
5998
"author": "Swashata Ghosh",

packages/scripts/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@babel/preset-typescript": "^7.1.0",
2323
"@types/browser-sync": "^0.0.42",
2424
"@types/node": "^10.11.3",
25+
"@types/signale": "^1.2.0",
2526
"@types/webpack": "^4.4.13",
2627
"@types/webpack-dev-middleware": "^2.0.2",
2728
"@types/webpack-hot-middleware": "^2.16.4",
@@ -37,6 +38,7 @@
3738
"optimize-css-assets-webpack-plugin": "^5.0.1",
3839
"postcss-loader": "^3.0.0",
3940
"sass-loader": "^7.1.0",
41+
"signale": "^1.3.0",
4042
"slugify": "^1.3.1",
4143
"style-loader": "^0.23.0",
4244
"uglifyjs-webpack-plugin": "^2.0.1",

packages/scripts/src/bin/index.ts

Lines changed: 217 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#!/usr/bin/env node
22
import program from 'commander';
33
import path from 'path';
4+
import signale from 'signale';
5+
import { ProjectConfig } from '../config/project.config.default';
6+
import { ServerConfig } from '../config/server.config.default';
7+
import { Build } from '../scripts/Build';
8+
import { Server } from '../scripts/Server';
49

510
/* tslint:disable:no-require-imports no-var-requires */
611
const pkg = require('../../package.json');
@@ -43,16 +48,68 @@ program
4348
'-s, --server-config [path]',
4449
'Path to server config. If it differs from ./wpackio.server.js'
4550
)
46-
.action(options => {
47-
isValidCommand = true;
48-
console.log('should start script.', options.context);
49-
// Set process.env.NODE_ENV to development
50-
// Set process.env.BABEL_ENV to development
51-
// Get project and server config JSONs.
52-
// Start the webpack/browserSync server
53-
// Listen for SIGTERM and quit properly
54-
// Listen for keyinput <r> and invalidate webpack builds.
55-
});
51+
.action(
52+
(
53+
options:
54+
| {
55+
context?: string;
56+
projectConfig?: string;
57+
serverConfig?: string;
58+
}
59+
| undefined
60+
) => {
61+
isValidCommand = true;
62+
signale.start('Starting up wpack.io development server');
63+
// Set process.env.NODE_ENV to development
64+
process.env.NODE_ENV = 'development';
65+
// Set process.env.BABEL_ENV to development
66+
process.env.BABEL_ENV = 'development';
67+
// Get project and server config JSONs.
68+
const cwd = resolveCWD(options);
69+
signale.info(`Using startup path: ${cwd}`);
70+
try {
71+
const {
72+
projectConfig,
73+
serverConfig,
74+
projectConfigPath,
75+
serverConfigPath,
76+
} = getProjectAndServerConfig(cwd, options);
77+
signale.info(`Using project config from ${projectConfigPath}`);
78+
signale.info(`Using server config from ${serverConfigPath}`);
79+
// Start the webpack/browserSync server
80+
const server: Server = new Server(
81+
projectConfig,
82+
serverConfig,
83+
cwd
84+
);
85+
server.serve();
86+
// Listen for SIGINT and quit properly
87+
process.on('SIGINT', () => {
88+
signale.complete('Gracefully ending development server');
89+
server.stop();
90+
signale.success(
91+
'To create production build, run `yarn build` or `npm run build`'
92+
);
93+
signale.star('Thank you for using https://wpack.io.');
94+
signale.star('To spread the ❤️ please tweet.');
95+
process.exit(0);
96+
});
97+
process.on('SIGKILL', () => {
98+
server.stop();
99+
});
100+
process.on('SIGTERM', () => {
101+
server.stop();
102+
});
103+
} catch (e) {
104+
signale.error(
105+
'Could not start development server. Please check the log below.'
106+
);
107+
signale.fatal(e);
108+
process.exit(1);
109+
}
110+
// Listen for keyinput <r> and invalidate webpack builds.
111+
}
112+
);
56113

57114
// Build the script
58115
program
@@ -69,21 +126,166 @@ program
69126
)
70127
.action(options => {
71128
isValidCommand = true;
72-
console.log('should build the script', options.context);
129+
signale.start('Creating production builds...');
73130
// Set process.env.NODE_ENV to production
131+
process.env.NODE_ENV = 'production';
74132
// Set process.env.BABEL_ENV to production
133+
process.env.BABEL_ENV = 'production';
75134
// Get project and server config JSONs.
76-
// Compile scripts using webpack
135+
const cwd = resolveCWD(options);
136+
signale.info(`Using startup path: ${cwd}`);
137+
try {
138+
const {
139+
projectConfig,
140+
serverConfig,
141+
projectConfigPath,
142+
serverConfigPath,
143+
} = getProjectAndServerConfig(cwd, options);
144+
signale.info(`Using project config from ${projectConfigPath}`);
145+
signale.info(`Using server config from ${serverConfigPath}`);
146+
// Start the webpack/browserSync server
147+
const build: Build = new Build(projectConfig, serverConfig, cwd);
148+
build
149+
.build()
150+
.then(log => {
151+
signale.success(
152+
'Build Successful. Please check the log below'
153+
);
154+
console.log(log);
155+
process.exit(0);
156+
})
157+
.catch(err => {
158+
signale.fatal(
159+
'Could not create production build. Please check the log below'
160+
);
161+
console.log(err);
162+
process.exit(1);
163+
});
164+
} catch (e) {
165+
signale.error(
166+
'Could not start development server. Please check the log below.'
167+
);
168+
signale.fatal(e);
169+
process.exit(1);
170+
}
77171
});
78172

79173
// Init
80174
program.parse(process.argv);
81175

82176
// error on unknown commands
83177
if (!isValidCommand) {
84-
console.error(
85-
'Invalid command: %s\nSee --help for a list of available commands.',
178+
signale.error(
179+
'Invalid command: %s\nSee usage below.\n\n',
86180
program.args.join(' ')
87181
);
88-
process.exit(1);
182+
program.help();
89183
}
184+
185+
/**
186+
* Resolve `cwd`, a.k.a, current working directory or context from user input.
187+
* It takes into account the `--context [path]` option from CLI and uses process
188+
* cwd, if not provided.
189+
*
190+
* @param options Options as received from CLI
191+
*/
192+
function resolveCWD(
193+
options: { context?: string | undefined } | undefined
194+
): string {
195+
let cwd = process.cwd();
196+
// If user has provided cwd, then use that instead
197+
if (options && options.context) {
198+
const { context } = options;
199+
if (path.isAbsolute(options.context)) {
200+
cwd = context;
201+
} else {
202+
cwd = path.resolve(cwd, context);
203+
}
204+
}
205+
206+
return cwd;
207+
}
208+
209+
// tslint:disable: non-literal-require
210+
function getProjectAndServerConfig(
211+
cwd: string,
212+
options: { projectConfig?: string; serverConfig?: string } | undefined
213+
): {
214+
projectConfig: ProjectConfig;
215+
serverConfig: ServerConfig;
216+
projectConfigPath: string;
217+
serverConfigPath: string;
218+
} {
219+
// Get the config file paths from options
220+
// If user is passing relative path, then it will be used along with cwd
221+
// If it is absolute path, then the absolute would be used instead
222+
// This is how path.resolve works.
223+
const projectConfigPath = path.resolve(
224+
cwd,
225+
options && options.projectConfig
226+
? options.projectConfig
227+
: 'wpackio.project.js'
228+
);
229+
230+
const serverConfigPath = path.resolve(
231+
cwd,
232+
options && options.serverConfig
233+
? options.serverConfig
234+
: 'wpackio.server.js'
235+
);
236+
237+
// Now create the configuration objects
238+
let projectConfig: ProjectConfig;
239+
let serverConfig: ServerConfig;
240+
241+
// First check to see if the files are present
242+
try {
243+
projectConfig = require(projectConfigPath) as ProjectConfig;
244+
} catch (e) {
245+
throw new Error(
246+
`Could not find project configuration at:\n${projectConfigPath}\nPlease make sure the file exists or adjust your --context or --project-config parameters.`
247+
);
248+
}
249+
try {
250+
serverConfig = require(serverConfigPath) as ServerConfig;
251+
} catch (e) {
252+
throw new Error(
253+
`Could not find server configuration at:\n${serverConfigPath}\nPlease make sure the file exists or adjust your --context or --server-config parameters.`
254+
);
255+
}
256+
257+
// Now validate them
258+
if (typeof projectConfig !== 'object') {
259+
throw new Error(
260+
`Project configuration must export an object literal. Right now it is ${typeof projectConfig}`
261+
);
262+
}
263+
if (typeof serverConfig !== 'object') {
264+
throw new Error(
265+
`Server configuration must export an object literal. Right now it is ${typeof serverConfig}`
266+
);
267+
}
268+
// @todo
269+
// Also validate the config, but let's leave it for now
270+
// Make sure to do it in future
271+
272+
return { projectConfig, serverConfig, projectConfigPath, serverConfigPath };
273+
}
274+
275+
// Error out on force close
276+
process.on('SIGKILL', () => {
277+
signale.fatal(
278+
'The operation failed because the process exited too early. ' +
279+
'This probably means the system ran out of memory or someone called ' +
280+
'`kill -9` on the process.'
281+
);
282+
process.exit(1);
283+
});
284+
process.on('SIGTERM', () => {
285+
signale.fatal(
286+
'The operation failed because the process exited too early. ' +
287+
'Someone might have called `kill` or `killall`, or the system could ' +
288+
'be shutting down.'
289+
);
290+
process.exit(1);
291+
});

0 commit comments

Comments
 (0)