b13-rocket 0.7.2 → 0.8.1

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 CHANGED
@@ -1,77 +1,125 @@
1
1
  # Rocket FE build setup
2
2
 
3
- ## Requirements
4
-
5
- * node = 16.13.0 (https://nodejs.org/en/download/)
6
- * npm = 6.4.1 (https://www.npmjs.com/get-npm)
7
- * yarn = 1.12.3 (https://yarnpkg.com/en/docs/install)
3
+ This Node CLI tool helps developers quickly create multiple frontend builds for site packages using **Vite 5**.
8
4
 
5
+ ## Requirements
9
6
 
10
- ## Init
7
+ * node >= 20.18.0 (https://nodejs.org/en/download/)
8
+ * npm >= 18.17.0 (https://www.npmjs.com/get-npm)
9
+ * yarn >= 3.0.0 (https://yarnpkg.com/en/docs/install)
10
+
11
+ <!--
12
+ ## Vite Plugins:
13
+ - Babel: https://github.com/owlsdepartment/vite-plugin-babel
14
+ - dynamic import: https://github.com/vite-plugin/vite-plugin-dynamic-import
15
+ - babel-compiler: https://github.com/yzydeveloper/vite-plugin-babel-compiler
16
+ - Critical CSS: https://github.com/nystudio107/rollup-plugin-critical
17
+ - Vite dts: https://github.com/qmhc/vite-plugin-dts
18
+ - Compression: https://github.com/nonzzz/vite-plugin-compression
19
+ - Chunk split: https://github.com/sanyuan0704/vite-plugin-chunk-split
20
+ - static copy: https://github.com/sapphi-red/vite-plugin-static-copy
21
+ - build progress: https://github.com/jeddygong/vite-plugin-progress
22
+ - image Optimizer: https://github.com/FatehAK/vite-plugin-image-optimizer
23
+ - externals plugin: https://github.com/crcong/vite-plugin-externals
24
+ - auto-import: https://github.com/antfu/unplugin-auto-import
25
+ - vitest: https://github.com/vitest-dev/vitest
26
+
27
+ ## Post CSS plugins:
28
+ - https://preset-env.cssdb.org/
29
+ - https://www.npmjs.com/package/postcss-nested
30
+
31
+ -->
11
32
 
12
- `yarn install`
33
+ ---
13
34
 
35
+ ## CLI Commands
14
36
 
15
- ## Build JS and CSS
37
+ To see available commands, run:
16
38
 
17
- `yarn rocket build`
39
+ ```bash
40
+ $ yarn rocket help
41
+ ````
18
42
 
19
- ## CLI Options
43
+ For example, to start a new build, you can run:
20
44
 
21
- `yarn rocket help`
45
+ ```bash
46
+ $ yarn rocket build --site=my-site
47
+ ```
22
48
 
23
49
  ---
24
50
 
25
- ## Caches
51
+ ## Config setup
26
52
 
27
- `webpack` and `babel-loader` build caches are stored in `node_modules/.cache/`
53
+ ### Shared Vite Config (`config/shared.vite.config.js`)
28
54
 
29
- ---
55
+ This file contains shared Vite configuration that applies to all packages. You can extend it as needed.
30
56
 
31
- ## TYPO3 Setup
57
+ ```js
58
+ import { defineConfig } from 'vite';
32
59
 
33
- Site Extension JS include setup:
60
+ export const sharedViteConfig = defineConfig({
61
+ resolve: {
62
+ alias: {
63
+ // ...
64
+ },
65
+ },
66
+ });
34
67
 
35
- ### constants.typoscript
36
- ```
37
- # enable hot module replacement (hmr)
38
- enableHMR = 0
39
- enableHMR := getEnv(TYPO3_TS_ENABLE_HMR)
40
68
  ```
41
69
 
42
- ### setup.typoscript
43
- ```
44
- page.includeJSFooter {
45
- vendor = EXT:YOUR_EXT_NAME/Resources/Public/JavaScript/common-vendor.js
46
- vendor.if.isFalse = {$enableHMR}
47
- vendor.type = module
48
- main = EXT:YOUR_EXT_NAME/Resources/Public/JavaScript/main.js
49
- main.if.isFalse = {$enableHMR}
50
- main.type = module
51
-
52
- # if hot module replacement is enabled
53
- vendor-hmr = https://DOMAIN:8088/typo3conf/ext/YOUR_EXT_NAME/Resources/Public/JavaScript/common-vendor-hmr.js
54
- vendor-hmr.if.isTrue = {$enableHMR}
55
- main-hmr = https://DOMAIN:8088/typo3conf/ext/YOUR_EXT_NAME/Resources/Public/JavaScript/main-hmr.js
56
- main-hmr.if.isTrue = {$enableHMR}
57
- }
70
+ ### Package-specific Config (config/XXX.package.js)
71
+
72
+ For each package, you can override certain configurations using this setup:
73
+
74
+ ```js
75
+ import { definePackageConfig } from 'b13-rocket';
76
+
77
+ export const config = definePackageConfig({
78
+ name: '', // package name
79
+ input: '', // entry js file
80
+ output: '', // output directory
81
+ root: '', // project root
82
+ viteConfig: {
83
+ // Override Vite config for this package
84
+ resolve: {
85
+ alias: {
86
+ // Define package-specific aliases here
87
+ },
88
+ },
89
+ },
90
+ });
91
+
58
92
  ```
59
93
 
60
94
  ---
61
95
 
62
- ## Update to Yarn v3
96
+ ## Extract CSS
63
97
 
64
- ```
98
+ To extract CSS from the Vite build, add the `external-` prefix to the CSS filename.
99
+
100
+ Example:
101
+
102
+ ```js
103
+ import 'external-rte.css';
104
+ ````
105
+
106
+ ---
107
+
108
+ ## Update
109
+
110
+ ### Update Yarn version and switch to vite
111
+
112
+ ```bash
65
113
  // switch to latest yarn version
66
- yarn set version berry
114
+ $ yarn set version berry
67
115
 
68
116
  // update node dependencies
69
- yarn install
70
- yarn remove b13-build-cli
71
- yarn add "b13-build-cli@ssh://git@code.b13.com/infrastructure/rocket-cli.git#^0.3.0"
117
+ $ yarn install
118
+ $ yarn remove b13-build-cli
119
+ $ yarn add "b13-build-cli@ssh://git@code.b13.com/public-projects/rocket-cli.git#vite5.2"
72
120
  ```
73
121
 
74
- Update .gitignore
122
+ ### Update .gitignore
75
123
  ```
76
124
  .pnp.*
77
125
  .yarn/*
@@ -82,7 +130,10 @@ Update .gitignore
82
130
  !.yarn/versions
83
131
  ```
84
132
 
85
- Update package.json script call: (use 'yarn node' instead of 'node')
133
+ ### Remove package.json 'rocket' script call
134
+
135
+ If your package.json still contains a rocket script, remove it to avoid conflicts with the new CLI version.
136
+
86
137
  ```
87
138
  ....
88
139
  "scripts": {
@@ -91,7 +142,7 @@ Update package.json script call: (use 'yarn node' instead of 'node')
91
142
  ...
92
143
  ```
93
144
 
94
- ## Use hmr inside ddev container
145
+ ### Use hmr inside ddev container
95
146
 
96
147
  1. Copy files from `files` directory to your `.ddev` directory.
97
148
  2. Restart ddev (`ddev restart`)
package/index.js CHANGED
@@ -1,4 +1,10 @@
1
- #!/usr/bin/env node
1
+ export function definePackageConfig({ name = '', input = '', output = '', root = '', viteConfig = {}}) {
2
2
 
3
- require = require('esm')(module);
4
- require('./src/cli').cli(process.argv);
3
+ return {
4
+ name,
5
+ input,
6
+ output,
7
+ root,
8
+ viteConfig,
9
+ };
10
+ }
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "b13-rocket",
3
3
  "description": "FE CLI build tool",
4
- "version": "0.7.2",
4
+ "version": "0.8.1",
5
+ "type": "module",
5
6
  "engines": {
6
7
  "node": ">=v16.13.0",
7
8
  "npm": ">=6.4.1",
@@ -12,55 +13,27 @@
12
13
  "email": "info@b13.com",
13
14
  "url": "https://b13.com/"
14
15
  },
15
- "scripts": {
16
- "rocket": "node ./index.js"
17
- },
18
16
  "bin": {
19
- "rocket": "./index.js"
17
+ "rocket": "src/cli.js"
20
18
  },
21
19
  "main": "index.js",
22
20
  "dependencies": {
23
- "@babel/core": "7",
24
- "@babel/plugin-transform-runtime": "7",
25
- "@babel/preset-env": "7",
26
- "@babel/preset-typescript": "7",
27
- "@babel/runtime": "7",
28
- "autoprefixer": "^10.4.13",
29
- "b13-eslint-config": "https://code.b13.com/public-projects/es-lint-config.git",
30
- "b13-stylelint-config": "https://code.b13.com/public-projects/stylelint-config.git#0.1.0",
31
- "babel-loader": "^8.2.5",
32
- "chalk": "^4.1.2",
33
- "child_process": "^1.0.2",
34
- "compression-webpack-plugin": "^7.1.2",
35
- "css-loader": "^5.2.7",
36
- "cssnano": "^5.1.14",
37
- "eslint": "^8",
38
- "eslint-plugin-vue": "^9.9.0",
39
- "esm": "^3.2.25",
40
- "expose-loader": "^2.0.0",
41
- "file-loader": "^6.2.0",
42
- "filesize": "^6.4.0",
43
- "html-loader": "^2.1.2",
44
- "less": "^4.1.3",
45
- "path": "^0.12.7",
46
- "postcss": "^8.4.16",
47
- "postcss-sort-media-queries": "^4.3.0",
48
- "readline": "^1.3.0",
49
- "sass": "^1.56.1",
50
- "sass-loader": "^11.1.1",
51
- "stylelint": "^14.16.1",
52
- "vue": "^2.7.0",
53
- "vue-loader": "^15.10.1",
54
- "vue-svg-inline-loader": "^2.1.5",
55
- "vue-template-compiler": "^2.7.10",
56
- "webpack": "^5.75.0",
57
- "webpack-cli": "^5.0.0",
58
- "webpack-dev-server": "^4.11.1",
59
- "webpack-merge": "^5.8.0",
60
- "workbox-webpack-plugin": "^6.5.4"
61
- },
62
- "devDependencies": {
63
- "webpack-bundle-analyzer": "^4.7.0"
21
+ "autoprefixer": "^10.4.19",
22
+ "chalk": "^5.3.0",
23
+ "cssnano": "^6.1.2",
24
+ "minimist": "^1.2.8",
25
+ "postcss": "^8.4.38",
26
+ "postcss-nested": "^6.0.1",
27
+ "postcss-preset-env": "^9.5.6",
28
+ "postcss-sort-media-queries": "^5.2.0",
29
+ "sass": "^1.75.0",
30
+ "sharp": "^0.32.6",
31
+ "svgo": "^3.2.0",
32
+ "tsconfig": "^7.0.0",
33
+ "vite": "^5.2.9",
34
+ "vite-plugin-image-optimizer": "^1.1.7",
35
+ "vite-plugin-require-support": "^1.6.1",
36
+ "vite-svg-loader": "^4.0.0"
64
37
  },
65
38
  "packageManager": "yarn@3.2.3",
66
39
  "dependenciesMeta": {
package/src/build.js CHANGED
@@ -1,158 +1,104 @@
1
- import { sites } from './sites';
2
- import path from 'path';
3
- import fs from 'fs';
4
- import { ScssBuild } from './scss/scssBuild';
5
- import { LessBuild } from './scss/lessBuild';
6
- import webpack from 'webpack';
7
- import { default as webpackConfig } from './webpack/webpack.config';
8
- import chalk from 'chalk';
9
- import { Notification } from './notification';
10
-
11
-
12
- class Build {
13
- constructor(config = {}, sitesConfigPath = '', mode = 'production') {
14
- this.sitesConfigPath = sitesConfigPath;
15
- this.config = config;
16
- this.mode = mode;
17
- }
18
-
19
- // make sure JS public directory exists and is clean
20
- clear() {
21
- const jsPath = path.resolve(this.sitesConfigPath, this.config.js.path.target);
22
- if (!fs.existsSync(jsPath)) {
23
- fs.mkdirSync(jsPath);
1
+ import { build as viteBuild, defineConfig, mergeConfig , createServer, loadEnv} from 'vite';
2
+ import { defaultViteConfig } from './vite/vite.config.js';
3
+ import fs from 'node:fs';
4
+
5
+ // post process manifest json
6
+ // remove all css files starting with 'external-' from manifest.json entry file
7
+ const postProcessManifest = (manifestPath = '') => {
8
+ fs.readFile(manifestPath, 'utf8', (err, data) => {
9
+ if (err) {
10
+ console.error('Error reading file:', err);
11
+ return;
24
12
  }
25
13
 
26
- fs.readdirSync(jsPath, { withFileTypes: true }).forEach((file) => {
27
-
28
- // only remove file
29
- // skip directories
30
- if (file.isFile()) {
31
- fs.unlinkSync(path.resolve(this.sitesConfigPath, `${this.config.js.path.target}/${file.name}`), (err) => {
32
- if (err) {
33
- throw err;
34
- }
35
- });
36
- }
37
- });
38
- }
39
-
40
- build() {
41
- const wpConfig = webpackConfig(this.config, this.sitesConfigPath, this.mode);
42
- const compiler = webpack(wpConfig);
14
+ let manifest;
15
+ try {
16
+ manifest = JSON.parse(data);
17
+ } catch (parseError) {
18
+ console.error('Error parsing JSON data:', parseError);
19
+ return;
20
+ }
43
21
 
44
- compiler.hooks.beforeRun.tap('b13-rocket-cli', (context, entry) => {
45
- this.clear();
46
- if (this.config.sw) {
47
- this.updateServiceWorkerBuildTimestamp();
22
+ for (const entry in manifest) {
23
+ if (manifest[entry].isEntry && manifest[entry].css) {
24
+ manifest[entry].css = manifest[entry].css.filter(cssFile => !cssFile.startsWith('external-'));
48
25
  }
49
- });
50
-
51
- compiler.run((err, stats) => {
52
-
53
- Notification.taskInfo('Process JavaScript file(s)');
26
+ }
54
27
 
55
- if (err) {
56
- Notification.error('JS build failed', err.stack || err);
57
- if (err.details) {
58
- Notification.error('JS build failed', err.details);
59
- }
28
+ fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2), 'utf8', writeErr => {
29
+ if (writeErr) {
30
+ console.error('Error writing file:', writeErr);
60
31
  return;
61
32
  }
62
-
63
- if (stats.hasErrors()) {
64
- Notification.error('JS build failed', stats.toString({
65
- chunks: false,
66
- colors: true,
67
- }));
68
- process.exit(1);
69
- }
70
-
71
- const info = stats.toJson();
72
- if (stats.hasWarnings()) {
73
- Notification.warn(info.warnings);
74
- }
75
-
76
- Notification.log(stats.toString({
77
- chunks: false,
78
- colors: true,
79
- }));
80
-
81
- compiler.close((closeErr) => {
82
-
83
- // ...
84
- });
85
33
  });
86
- }
34
+ });
35
+ }
87
36
 
88
- // update service worker build timestamp to purge service worker cache
89
- updateServiceWorkerBuildTimestamp() {
90
- fs.readFile(
91
- path.resolve(this.sitesConfigPath, `${this.config.sw.path.source}/${this.config.sw.filename.main}.js`),
92
- 'utf8',
93
- (err, data) => {
94
- if (err) {throw err;}
95
- const timestamp = (Date.now() / 1000 | 0).toString();
96
- const result = data.replace(/const\sbuildTimestamp\s=\s\'\d{0,10}\'\;/g, `const buildTimestamp = '${timestamp}';`);
97
- fs.writeFile(
98
- path.resolve(this.sitesConfigPath, `${this.config.sw.path.source}/${this.config.sw.filename.main}.js`),
99
- result,
100
- 'utf8',
101
- (err) => {
102
- if (err) {throw err;}
103
- console.log('Updated service worker build timestamp');
104
- },
105
- );
37
+ async function vite(config = {}, sharedViteConfig = {}, enableServer = false) {
38
+
39
+ let viteConfig = mergeConfig(
40
+ defaultViteConfig,
41
+ {
42
+ root : config.root,
43
+ build: {
44
+ rollupOptions: {
45
+ input: config.input,
46
+ },
47
+ outDir: config.output,
106
48
  },
49
+ },
50
+ false,
51
+ );
52
+
53
+ // merge shared vite config
54
+ if (Object.keys(sharedViteConfig).length > 0) {
55
+ viteConfig = mergeConfig(
56
+ viteConfig,
57
+ sharedViteConfig,
58
+ false,
107
59
  );
108
60
  }
109
- }
110
-
111
61
 
112
- export async function build(args) {
113
- const { siteConfig } = await sites(args);
114
-
115
- if (!args.sitesConfigPath) {
116
- Notification.error('missing site build config');
117
- return;
62
+ // marge site package specific vite config
63
+ if (config?.viteConfig && Object.keys(config.viteConfig).length > 0) {
64
+ viteConfig = mergeConfig(
65
+ viteConfig,
66
+ config.viteConfig,
67
+ false,
68
+ );
118
69
  }
119
70
 
120
- const sitesConfigPath = args.sitesConfigPath;
121
- const mode = args.mode ? args.mode : 'production';
122
- const target = args.target ? args.target : 'all';
123
-
124
- for (const [key, site] of siteConfig) {
125
- if (args.site && key !== args.site) {
126
-
127
- // skip other sites
128
- continue;
129
- }
130
-
131
- if (args.bundleAnalyzer) {
132
- site.config.bundleAnalyzer = true;
133
- }
134
-
135
- if (site.hasScss() && ['all', 'scss'].includes(target)) {
136
- const scss = new ScssBuild(site.config, sitesConfigPath);
137
- scss.clear();
138
- scss.build();
139
- }
140
-
141
- if (site.hasLess() && ['all', 'less'].includes(target)) {
142
- const less = new LessBuild(site.config, sitesConfigPath);
143
- less.clear();
144
- less.build();
71
+ if (enableServer) {
72
+ const vitePort = process.env.VITE_HMR_PORT || 5173;
73
+ viteConfig.mode = 'development';
74
+
75
+ if (process.env.DDEV_PRIMARY_URL !== undefined) {
76
+ const server = await createServer({
77
+ ...viteConfig,
78
+ configFile: false,
79
+ server: {
80
+ host: true,
81
+ origin: `${process.env.DDEV_PRIMARY_URL}:${vitePort}`
82
+ },
83
+ })
84
+ await server.listen();
85
+ console.log(`${config.name} HMR is ready 🚀`);
86
+ } else {
87
+ console.log('⚠️ ERROR: DDEV_PRIMARY_URL missing');
145
88
  }
89
+ } else {
90
+ await viteBuild(viteConfig);
91
+ const manifestPath = config.output + '/.vite/manifest.json';
92
+ postProcessManifest(manifestPath);
93
+ }
94
+ }
146
95
 
147
- if (site.hasJs() && ['all', 'js'].includes(target)) {
148
- const wpBuild = new Build(site.config, sitesConfigPath, mode);
149
- wpBuild.build();
150
- }
151
-
152
- if (args.site && key === args.site) {
153
-
154
- // required site build is done
155
- break;
96
+ export async function build(sitesConfig = {}, args = '', enableServer = false) {
97
+ if (args.site && sitesConfig.sites.get(args.site)) {
98
+ vite(sitesConfig.sites.get(args.site).config, sitesConfig.sharedConfig, enableServer);
99
+ } else {
100
+ for (const [key, site] of sitesConfig.sites) {
101
+ vite(site.config, sitesConfig.sharedConfig);
156
102
  }
157
103
  }
158
104
  }
package/src/cli.js CHANGED
@@ -1,57 +1,40 @@
1
- import minimist from 'minimist';
2
- import { help } from './help';
3
- import { build } from './build';
4
- import { hmr } from './hmr';
5
- import { version } from './version';
6
- import { stylelint } from './stylelint';
7
- import { create } from './create';
8
- import path from 'path';
9
-
10
- export async function cli(argsArray) {
11
- const args = minimist(argsArray.slice(2));
12
- let cmd = args._[0] || 'help';
13
-
14
- // add default site config path
15
- if (!args.sitesConfigPath) {
16
- args.sitesConfigPath = './config';
17
- }
18
- args.sitesConfigPath = path.resolve(process.env.INIT_CWD, args.sitesConfigPath);
19
-
20
- if (args.version || args.v) {
21
- cmd = 'version';
22
- }
23
-
24
- if (args.help || args.h) {
25
- cmd = 'help';
26
- }
1
+ #!/usr/bin/env node
27
2
 
28
- switch (cmd) {
29
- case 'version':
30
- version(args);
31
- break;
32
-
33
- case 'help':
34
- help(args);
35
- break;
36
-
37
- case 'build':
38
- build(args);
39
- break;
40
-
41
- case 'hmr':
42
- hmr(args);
43
- break;
44
-
45
- case 'stylelint':
46
- stylelint(args);
47
- break;
48
-
49
- case 'create':
50
- create(args);
51
- break;
52
-
53
- default:
54
- console.error(`"${cmd}" is not a valid command!`);
3
+ import path from 'node:path';
4
+ import minimist from 'minimist';
5
+ import { build } from './build.js';
6
+ import { sites } from './sites.js';
7
+ import { help } from './help.js';
8
+ import { version } from './version.js';
9
+ import { Notification } from "./notification.js";
10
+
11
+ const args = minimist(process.argv.slice(2));
12
+ const cmd = args._[0] || 'help';
13
+
14
+ // add default site config path
15
+ if (!args.sitesConfigPath) {
16
+ args.sitesConfigPath = './config';
17
+ }
18
+ args.sitesConfigPath = path.resolve(process.env.INIT_CWD, args.sitesConfigPath);
19
+ const sitesConfig = await sites(args);
20
+
21
+ switch (cmd) {
22
+ case 'version':
23
+ Notification.log(version)
24
+ break;
25
+ case 'build':
26
+ build(sitesConfig, args);
27
+ break;
28
+ case 'hmr':
29
+ if (!args.site) {
30
+ Notification.error('missing --site= name');
55
31
  break;
56
- }
32
+ }
33
+ build(sitesConfig, args, true);
34
+ break;
35
+ case 'help':
36
+ help(sitesConfig, args);
37
+ break;
38
+ default:
39
+ Notification.error(`'${cmd}' command doesn't exist.`);
57
40
  }