mirror of
https://github.com/HeyPuter/puter.git
synced 2025-02-02 22:43:45 +08:00
dev: bundle gui in dev
This commit is contained in:
parent
0d01d1f800
commit
8ad435a0ea
8
package-lock.json
generated
8
package-lock.json
generated
@ -2545,6 +2545,10 @@
|
|||||||
"resolved": "src/backend",
|
"resolved": "src/backend",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@heyputer/gui": {
|
||||||
|
"resolved": "src/gui",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@heyputer/kv.js": {
|
"node_modules/@heyputer/kv.js": {
|
||||||
"version": "0.1.6",
|
"version": "0.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/@heyputer/kv.js/-/kv.js-0.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/@heyputer/kv.js/-/kv.js-0.1.6.tgz",
|
||||||
@ -16790,8 +16794,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/gui": {
|
"src/gui": {
|
||||||
"version": "2.3.0",
|
"name": "@heyputer/gui",
|
||||||
"extraneous": true,
|
"version": "2.4.0",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"src/*"
|
"src/*"
|
||||||
|
@ -48,6 +48,12 @@ class SelfHostedModule extends AdvancedBase {
|
|||||||
command: 'npm',
|
command: 'npm',
|
||||||
args: ['run', 'start-webpack'],
|
args: ['run', 'start-webpack'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'gui:webpack-watch',
|
||||||
|
directory: 'src/gui',
|
||||||
|
command: 'npm',
|
||||||
|
args: ['run', 'start-webpack'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'terminal:rollup-watch',
|
name: 'terminal:rollup-watch',
|
||||||
directory: 'src/terminal',
|
directory: 'src/terminal',
|
||||||
|
@ -255,46 +255,9 @@ class PuterHomepageService extends BaseService {
|
|||||||
? `<script>window.gui_env = 'prod';</script>`
|
? `<script>window.gui_env = 'prod';</script>`
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
${
|
|
||||||
((!bundled && manifest?.lib_paths)
|
|
||||||
? manifest.lib_paths.map(path => `<script type="text/javascript" src="${path}"></script>\n`)
|
|
||||||
: []).join('')
|
|
||||||
}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
window.icons = {};
|
|
||||||
|
|
||||||
${(() => {
|
|
||||||
if ( !(!bundled && manifest) ) return '';
|
|
||||||
const html = [];
|
|
||||||
fs_.readdirSync(path_.join(gui_path, 'src/icons')).forEach(file => {
|
|
||||||
// skip dotfiles
|
|
||||||
if(file.startsWith('.'))
|
|
||||||
return;
|
|
||||||
// load image
|
|
||||||
let buff = new Buffer.from(fs_.readFileSync(path_.join(gui_path, 'src/icons') + '/' + file));
|
|
||||||
// convert to base64
|
|
||||||
let base64data = buff.toString('base64');
|
|
||||||
// add to `window.icons`
|
|
||||||
if(file.endsWith('.png'))
|
|
||||||
html.push(`window.icons['${file}'] = "data:image/png;base64,${base64data}";\n`);
|
|
||||||
else if(file.endsWith('.svg'))
|
|
||||||
html.push(`window.icons['${file}'] = "data:image/svg+xml;base64,${base64data}";\n`);
|
|
||||||
})
|
|
||||||
return html.join('');
|
|
||||||
})()}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
${
|
|
||||||
((!bundled && manifest?.js_paths)
|
|
||||||
? manifest.js_paths.map(path => writeScriptTag(path))
|
|
||||||
: []).join('')
|
|
||||||
}
|
|
||||||
<!-- Load the GUI script -->
|
<!-- Load the GUI script -->
|
||||||
<script ${
|
<script src="/dist/gui.bundle.js"></script>
|
||||||
// !bundled ? ' type="module"' : ''
|
|
||||||
' type="module"'
|
|
||||||
} src="${(!bundled && manifest?.index) || '/dist/gui.js'}"></script>
|
|
||||||
<!-- Initialize GUI when document is loaded -->
|
<!-- Initialize GUI when document is loaded -->
|
||||||
<script type="module">
|
<script type="module">
|
||||||
window.addEventListener('load', function() {
|
window.addEventListener('load', function() {
|
||||||
|
81
src/gui/doc/webpack_attempts.md
Normal file
81
src/gui/doc/webpack_attempts.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
Multiple things attempted when trying to add icons to the bundle.
|
||||||
|
|
||||||
|
None of this worked - eventually just prepended text on emit instead.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// compilation.hooks.processAssets.tap(
|
||||||
|
// {
|
||||||
|
// name: 'AddImportPlugin',
|
||||||
|
// stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
|
||||||
|
// },
|
||||||
|
// (assets) => {
|
||||||
|
// for (const assetName of Object.keys(assets)) {
|
||||||
|
// if (assetName.endsWith('.js')) {
|
||||||
|
// const source = assets[assetName].source();
|
||||||
|
// const newSource = `${icons}\n${source}`;
|
||||||
|
// compilation.updateAsset(assetName, new compiler.webpack.sources.RawSource(newSource));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// Inject into bundle
|
||||||
|
// console.log('adding this:' + icons);
|
||||||
|
// compilation.assets['icons-thing'] = {
|
||||||
|
// source: () => icons,
|
||||||
|
// size: () => icons.length,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// compilation.addModule({
|
||||||
|
// identifier() {
|
||||||
|
// return 'icons-thing';
|
||||||
|
// },
|
||||||
|
// build() {
|
||||||
|
// this._source = {
|
||||||
|
// source() {
|
||||||
|
// return content;
|
||||||
|
// },
|
||||||
|
// size() {
|
||||||
|
// return content.length;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
// Add the generated module to Webpack's internal modules
|
||||||
|
// compilation.hooks.optimizeModules.tap('IconsPlugin', (modules) => {
|
||||||
|
// const virtualModule = {
|
||||||
|
// identifier: () => 'icons.js',
|
||||||
|
// readableIdentifier: () => 'icons.js',
|
||||||
|
// build: () => {},
|
||||||
|
// source: () => icons,
|
||||||
|
// size: () => icons.length,
|
||||||
|
// chunks: [],
|
||||||
|
// assets: [],
|
||||||
|
// hash: () => 'icons',
|
||||||
|
// };
|
||||||
|
|
||||||
|
// modules.push(virtualModule);
|
||||||
|
// });
|
||||||
|
|
||||||
|
});
|
||||||
|
// this.hooks.entryOption.tap('IconsPlugin', (context, entry) => {
|
||||||
|
// entry.main.import.push('icons-thing');
|
||||||
|
// });
|
||||||
|
// this.hooks.make.tapAsync('InjectTextEntryPlugin', (compilation, callback) => {
|
||||||
|
// // Create a new asset (fake module) from the generated content
|
||||||
|
// const content = `console.log('${this.options.text}');`;
|
||||||
|
|
||||||
|
// callback();
|
||||||
|
// });
|
||||||
|
// this.hooks.entryOption.tap('IconsPlugin', (context, entry) => {
|
||||||
|
// });
|
||||||
|
// this.hooks.entryOption.tap('InjectTextEntryPlugin', (context, entry) => {
|
||||||
|
// // Add this as an additional entry point
|
||||||
|
// this.options.entry = {
|
||||||
|
// ...this.options.entry,
|
||||||
|
// 'generated-entry': '// FINDME\n'
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
```
|
@ -28,7 +28,8 @@
|
|||||||
"test": "mocha ./packages/phoenix/test ./packages/phoenix/packages/contextlink/test",
|
"test": "mocha ./packages/phoenix/test ./packages/phoenix/packages/contextlink/test",
|
||||||
"start=gui": "nodemon --exec \"node dev-server.js\" ",
|
"start=gui": "nodemon --exec \"node dev-server.js\" ",
|
||||||
"build": "node ./build.js",
|
"build": "node ./build.js",
|
||||||
"check-translations": "node tools/check-translations.js"
|
"check-translations": "node tools/check-translations.js",
|
||||||
|
"start-webpack": "webpack --watch --devtool source-map"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"src/*"
|
"src/*"
|
@ -61,13 +61,15 @@ window.gui = async function(options){
|
|||||||
// DEV: Load the initgui.js file if we are in development mode
|
// DEV: Load the initgui.js file if we are in development mode
|
||||||
if(!window.gui_env || window.gui_env === "dev"){
|
if(!window.gui_env || window.gui_env === "dev"){
|
||||||
await window.loadScript('/sdk/puter.dev.js');
|
await window.loadScript('/sdk/puter.dev.js');
|
||||||
await window.loadScript(`${options.asset_dir}/initgui.js`, {isModule: true});
|
await window.loadScript('/putil.js/v1');
|
||||||
|
// await window.loadScript(`${options.asset_dir}/initgui.js`, {isModule: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
// PROD: load the minified bundles if we are in production mode
|
// PROD: load the minified bundles if we are in production mode
|
||||||
// note: the order of the bundles is important
|
// note: the order of the bundles is important
|
||||||
// note: Build script will prepend `window.gui_env="prod"` to the top of the file
|
// note: Build script will prepend `window.gui_env="prod"` to the top of the file
|
||||||
else if(window.gui_env === "prod"){
|
else if(window.gui_env === "prod"){
|
||||||
|
await window.loadScript('https://js.puter.com/putil/v1/');
|
||||||
await window.loadScript('https://js.puter.com/v2/');
|
await window.loadScript('https://js.puter.com/v2/');
|
||||||
// Load the minified bundles
|
// Load the minified bundles
|
||||||
await window.loadCSS('/dist/bundle.min.css');
|
await window.loadCSS('/dist/bundle.min.css');
|
||||||
|
@ -20,10 +20,12 @@ import { encode } from 'html-entities';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import webpack from 'webpack';
|
import webpack from 'webpack';
|
||||||
|
import webpack_config from './webpack.config.cjs';
|
||||||
import CleanCSS from 'clean-css';
|
import CleanCSS from 'clean-css';
|
||||||
import uglifyjs from 'uglify-js';
|
import uglifyjs from 'uglify-js';
|
||||||
import { lib_paths, css_paths, js_paths } from './src/static-assets.js';
|
import { lib_paths, css_paths, js_paths } from './src/static-assets.js';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
import BaseConfig from './webpack/BaseConfig.cjs';
|
||||||
|
|
||||||
// Polyfill __dirname, which doesn't exist in modules mode
|
// Polyfill __dirname, which doesn't exist in modules mode
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
@ -128,14 +130,8 @@ async function build(options){
|
|||||||
main_array.push(path.join(__dirname, 'src', js_paths[i]));
|
main_array.push(path.join(__dirname, 'src', js_paths[i]));
|
||||||
}
|
}
|
||||||
webpack({
|
webpack({
|
||||||
|
...BaseConfig(options),
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
entry: {
|
|
||||||
main: main_array,
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
path: path.resolve(__dirname, 'dist'),
|
|
||||||
filename: '[name].js',
|
|
||||||
},
|
|
||||||
optimization: {
|
optimization: {
|
||||||
minimize: true,
|
minimize: true,
|
||||||
},
|
},
|
||||||
@ -147,9 +143,9 @@ async function build(options){
|
|||||||
if(options?.verbose)
|
if(options?.verbose)
|
||||||
console.log(stats.toString());
|
console.log(stats.toString());
|
||||||
// write to ./dist/bundle.min.js
|
// write to ./dist/bundle.min.js
|
||||||
fs.writeFileSync(path.join(__dirname, 'dist', 'bundle.min.js'), icons + '\n\n\n' + js + '\n\n\n' + fs.readFileSync(path.join(__dirname, 'dist', 'main.js')));
|
// fs.writeFileSync(path.join(__dirname, 'dist', 'bundle.min.js'), fs.readFileSync(path.join(__dirname, 'dist', 'main.js')));
|
||||||
// remove ./dist/main.js
|
// remove ./dist/main.js
|
||||||
fs.unlinkSync(path.join(__dirname, 'dist', 'main.js'));
|
// fs.unlinkSync(path.join(__dirname, 'dist', 'main.js'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Copy index.js to dist/gui.js
|
// Copy index.js to dist/gui.js
|
||||||
|
8
src/gui/webpack.config.cjs
Normal file
8
src/gui/webpack.config.cjs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
const BaseConfig = require('./webpack/BaseConfig.cjs');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
...BaseConfig(),
|
||||||
|
optimization: {
|
||||||
|
minimize: false
|
||||||
|
},
|
||||||
|
};
|
27
src/gui/webpack/BaseConfig.cjs
Normal file
27
src/gui/webpack/BaseConfig.cjs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const EmitPlugin = require('./EmitPlugin.cjs');
|
||||||
|
module.exports = (options) => {
|
||||||
|
const config = {};
|
||||||
|
config.entry = [
|
||||||
|
'./src/init_sync.js',
|
||||||
|
'./src/init_async.js',
|
||||||
|
'./src/initgui.js',
|
||||||
|
'./src/helpers.js',
|
||||||
|
'./src/IPC.js',
|
||||||
|
'./src/globals.js',
|
||||||
|
'./src/i18n/i18n.js',
|
||||||
|
'./src/keyboard.js',
|
||||||
|
'./src/index.js',
|
||||||
|
];
|
||||||
|
config.output = {
|
||||||
|
path: path.resolve(__dirname, '../dist'),
|
||||||
|
filename: 'gui.bundle.js',
|
||||||
|
};
|
||||||
|
config.plugins = [
|
||||||
|
EmitPlugin({
|
||||||
|
options,
|
||||||
|
dir: path.join(__dirname, '../src/icons'),
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
return config;
|
||||||
|
};
|
78
src/gui/webpack/EmitPlugin.cjs
Normal file
78
src/gui/webpack/EmitPlugin.cjs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const uglifyjs = require('uglify-js');
|
||||||
|
|
||||||
|
module.exports = ({ dir, options }) => function () {
|
||||||
|
const compiler = this;
|
||||||
|
compiler.hooks.emit.tapAsync('EmitPlugin', async (compilation, callback) => {
|
||||||
|
let prefix_text = '';
|
||||||
|
prefix_text += 'window.gui_env="dev";\n';
|
||||||
|
|
||||||
|
// -----------------------------------------------
|
||||||
|
// Combine all images into a single js file
|
||||||
|
// -----------------------------------------------
|
||||||
|
{
|
||||||
|
let icons = 'window.icons = [];\n';
|
||||||
|
fs.readdirSync(dir).forEach(file => {
|
||||||
|
// skip dotfiles
|
||||||
|
if (file.startsWith('.'))
|
||||||
|
return;
|
||||||
|
// load image
|
||||||
|
let buff = new Buffer.from(fs.readFileSync(dir + '/' + file));
|
||||||
|
// convert to base64
|
||||||
|
let base64data = buff.toString('base64');
|
||||||
|
// add to `window.icons`
|
||||||
|
if (file.endsWith('.png'))
|
||||||
|
icons += `window.icons['${file}'] = "data:image/png;base64,${base64data}";\n`;
|
||||||
|
else if (file.endsWith('.svg'))
|
||||||
|
icons += `window.icons['${file}'] = "data:image/svg+xml;base64,${base64data}";\n`;
|
||||||
|
});
|
||||||
|
prefix_text += icons + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------
|
||||||
|
// Concat/merge the JS libraries and save them to ./dist/libs.js
|
||||||
|
// -----------------------------------------------
|
||||||
|
{
|
||||||
|
const lib_paths = require('./libPaths.cjs');
|
||||||
|
let js = '';
|
||||||
|
for(let i = 0; i < lib_paths.length; i++){
|
||||||
|
const file = path.join(__dirname, '../src/lib/', lib_paths[i]);
|
||||||
|
// js
|
||||||
|
if(file.endsWith('.js') && !file.endsWith('.min.js')){
|
||||||
|
let minified_code = await uglifyjs.minify(fs.readFileSync(file).toString(), {mangle: false});
|
||||||
|
if(minified_code && minified_code.code){
|
||||||
|
js += minified_code.code;
|
||||||
|
if(options?.verbose)
|
||||||
|
console.log('minified: ', file);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
js += fs.readFileSync(file);
|
||||||
|
if(options?.verbose)
|
||||||
|
console.log('skipped minification: ', file);
|
||||||
|
}
|
||||||
|
|
||||||
|
js += '\n\n\n';
|
||||||
|
}
|
||||||
|
prefix_text += js;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------
|
||||||
|
// Webpack understands this code better than I do
|
||||||
|
// -----------------------------------------------
|
||||||
|
Object.keys(compilation.assets).forEach((assetName) => {
|
||||||
|
if (assetName.endsWith('.js')) {
|
||||||
|
const asset = compilation.assets[assetName];
|
||||||
|
const originalSource = asset.source();
|
||||||
|
const newSource = `${prefix_text}\n${originalSource}`;
|
||||||
|
compilation.assets[assetName] = {
|
||||||
|
source: () => newSource,
|
||||||
|
size: () => newSource.length,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('END');
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
};
|
15
src/gui/webpack/libPaths.cjs
Normal file
15
src/gui/webpack/libPaths.cjs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module.exports = [
|
||||||
|
"jquery-3.6.1/jquery-3.6.1.min.js",
|
||||||
|
"viselect.min.js",
|
||||||
|
"FileSaver.min.js",
|
||||||
|
"socket.io/socket.io.min.js",
|
||||||
|
"qrcode.min.js",
|
||||||
|
"jquery-ui-1.13.2/jquery-ui.min.js",
|
||||||
|
"lodash@4.17.21.min.js",
|
||||||
|
"jquery.dragster.js",
|
||||||
|
"html-entities.js",
|
||||||
|
"timeago.min.js",
|
||||||
|
"iro.min.js",
|
||||||
|
"isMobile.min.js",
|
||||||
|
"jszip-3.10.1.min.js"
|
||||||
|
];
|
Loading…
Reference in New Issue
Block a user