I'm writing code in Javascript for Espruino (an embedded platform) and there is a restriction: Only one file is allowed to be saved into the device.
For the following code to work:
var x = new require("Something");
x.hello()
Something module should be reachable from main.js file. The Something module is a separate file and looks like this:
function Something() {
....
}
Something.prototype.hello = function() {
console.log("Hello there!");
}
exports = Something;
Question is; How can I concatenate these two files and still use the Something module as require("Something"); format?
The answer is found in Espruino forums:
# create bundle
BUNDLE="init.min.js"
echo "" > ${BUNDLE}
# Register modules via `Modules.addCached()` method
# see: http://forum.espruino.com/comments/12899741/
MODULE_NAME="FlashEEPROM"
MODULE_STR=$(uglifyjs -c -m -- ${MODULE_NAME}.js | sed 's/\"/\\\"/g' | sed "s/\n//g")
echo "Modules.addCached(\"${MODULE_NAME}\", \"${MODULE_STR}\");" >> ${BUNDLE}
uglifyjs -c -m -- init.js >> ${BUNDLE}
Why don't you use webpack to bundle the modules files into one file.
I suppose that your current directory is your project directory
First install nodejs at:
https://nodejs.org/en/download/
or sudo apt-get install nodejs
Second, install webpack using this command
npm i -g webpack
bundle your module
To build your bundle run this command:
webpack ./main.js bundle.js
Note: your bundle.js will include all the module files that you have required in main.js
There is https://www.npmjs.com/package/espruino tool that has function to prepare code (concatenate + minimize) for uploading to your board.
I use it in my build proc that compiles typescript code to javascript and then prepares for board upload. Tutorial is here https://github.com/espruino/EspruinoDocs/blob/master/tutorials/Typescript%20and%20Visual%20Studio%20Code%20IDE.md
Yes like it's mentioned above, you need to uglify the code. You cannot use webpack or grunt here. They will transpile the code which will break your require libraries.
Here is how I achieved this in my case:
I put all my files inside a folder (like /src). Don't import one file from another. Then minify all files in the folder into a single file (eg. index.js)
uglifyjs src/* --compress --mangle -o ./index.js
Then just upload this index.js into espruino. You need to install this library globally first.
npm install -g espruino
espruino -p /dev/cu.wchusbserial1420 -b 115200 --board ESP8266_4MB.json -e 'save()' index.js
I made a simple example here:
https://github.com/aliustaoglu/espruino-http-server
Related
In the package.json in my Angular 6 project, we have a bunch of node scripts to run and build our project.
I created a new script to process a scss file into an output directory:
"unbranded": "node-sass -x --output-style expanded ./client/src/app/demo/unbrandeddemo/unbranded.scss > ./dspackage/dist/css/unbranded.css",
This creates a css file at ./dspackage/dist/css/unbranded.css
Now I need to find and remove a string in this file after it's made. So I created tried installing the replace-in-file npm package and am trying
"postunbranded": "replace-in-file from to ./dspackage/dist/css/unbranded.css, ./dspackage/dist/css/unbranded.css --configFile=replace-config.js"
Where the replace-config-js is a file in the same directory as the package.json,
const options = {
from: /::ng-deep/g,
to: ''
};
I've tried various versions of this setup, but get the error:
Error: must provide pattern
So I want to write shared code in typescript, make an npm package of it and be able to install it..
So I tried writing an external lib like this :
export class Lib {
constructor(){
}
getData(){
console.log('getting data from lib');
}
}
Running npm link on external lib
And running npm link "package" in consuming apps directory, to have it appear in it's node_modules
consuming-app
index.ts
node_modules/
external-package-with-typescript
index.ts is simple it just looks like :
import { Lib } from 'external-package-with-typescript'
var l = new Lib();
Then I try to bundle it all with
browser index.ts -p tsify --global --debug > bundle.js
This results in an error from the external package
'import' and 'export' may appear only with 'sourceType: module'
I can get it to work with https://github.com/basarat/ts-npm-module-consume
But that produces an output that looks like
consuming-app/ index.ts
external-package-with-typescript/ index.ts
Which is of no value to me as I want one .js file that I can include in index.html
Ideas anyone?
Have you tried using declare instead of export?
I would like to bundle a largish node.js cli application into a single .js file.
My code is structured as follows:
|- main.js
|--/lib
|----| <bunch of js files>
|--/util
|----| <bunch of js files>
...etc
I can use browserify to bundle the whole thing into one file using main.js as the entry point, but Browserify assumes the runtime environment is a browser and substitutes its own libraries (e.g. browserify-http for http). So I'm looking for a browserify-for-node command
I tried running
$ browserify -r ./main.js:start --no-builtins --no-browser-field > myapp.js
$ echo "require('start') >> myapp.js
but I'm getting a bunch of errors when I try to run $ node myapp.js.
The idea is that the entire application with all dependencies except the core node dependencies is now in a single source file and can be run using
$ node myapp.js
Update
=============
JMM's answer below works but only on my machine. The bundling still does not capture all dependencies, so when I try to run the file on another machine, I get dependency errors like
ubuntu#ip-172-31-42-188:~$ node myapp.js
fs.js:502
return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
^
Error: ENOENT, no such file or directory '/Users/ruchir/dev/xo/client/node_modules/request/node_modules/form-data/node_modules/mime/types/mime.types'
You can use pkg by Zeit and follow the below steps to do so:
npm i pkg -g
Then in your NodeJS project, in package JSON include the following:
"pkg": {
"scripts": "build/**/*.js",
"assets": "views/**/*"
}
"main": "server.js"
Inside main parameter write the name of the file to be used as the entry point for the package.
After that run the below command in the terminal of the NodeJS project
pkg server.js --target=node12-linux-x64
Or you can remove target parameter from above to build the package for Windows, Linux and Mac.
After the package has been generated you have to give permissions to write:
chmod 777 ./server-linux
And then you can run it in your terminal by
./server-linux
This method will give you can executable file instead of a single .js file
Check out the --node option, and the other more granular options it incorporates.
I'm attempting to do a build of Bitcoinjs for browser testing folloing the instructions on the BitcoinJS page (included below).
$ npm install -g bitcoinjs-lib
$ npm -g install bitcoinjs-lib browserify uglify-js
$ browserify -r bitcoinjs-lib -s Bitcoin | uglifyjs > bitcoinjs.min.js
When I run this is does generate a file called bitcoinjs.min.js but it is empty. Can anyone explain what I'm doing wrong?
what does your index.js look like?
try the following: Create index.js with the following content in the same folder:
var bitcoin = {
base58: require('bs58'),
bitcoin: require('bitcoinjs-lib'),
ecurve: require('ecurve'),
BigInteger: require('bigi'),
Buffer: require('buffer'),
elliptic: require('elliptic'),
bs58check: require('bs58check'),
}
module.exports = bitcoin;
Then run:
browserify index.js -s bitcoin | uglifyjs > bitcoinjs.min.js
I can successfully compile my TypeScript project into a single JS file with source maps using something like this:
tsc --sourcemap --out app.js app.ts
I can also successfully minify that output using UglifyJS, while keeping source maps intact:
uglifyjs app.js --source-map app.js.map --in-source-map app.js.map -o app.js
However, I would like to go slightly further. I want to combine my compiled TypeScript code (app.js) with a couple third-party JS libraries into a single minified file that maintains source maps pointing back to the original TypeScript (for my code) or JavaScript (for the third-party libraries).
I tried something like this, basically just adding a JS library file to the input to UglifyJS:
uglifyjs app.js lib/javascript-library.js --source-map app.js.map --in-source-map app.js.map -o app.js
Unfortunately, that doesn't seem to work. It does successfully combine everything into one file, and the source maps for the TypeScript code seem to be preserved. But when I put an error in lib/javascript-library.js, the JS console in my browser (using source maps) says the error is in one of my TypeScript files, which is obviously wrong.
I am a TypeScript newb and I can't imagine I'm the first one to want to combine TS output with random JS libraries in a single minified file with source maps, but I can't find anyone talking about it. So maybe my approach is just completely wrong?
Typescript compiler isn't so smart, to do this you need use more specific tools. Example: gulpjs.
Requirements (if you know gulpjs skip this):
install nodejs
run this: npm install -g typescript gulp to install gulp taskrunner
in project directory, run npm init and follow instruction to create package.json
run: npm install gulp gulp-typescript gulp-concat gulp-uglify gulp-sourcemaps --save-dev to install ts compile, concat, uglify e generate sourcemaps tools
create file with name gulpfile.js
Define 'compile' task in gulpfile.js :
var gulp = require('gulp');
var ts = require('gulp-typescript');
var concat = require('gulp-concat');
var sourcemaps = require('gulp-sourcemaps');
var uglify = require('gulp-uglify');
gulp.task('compile', function() {
var tsResult = gulp.src('app.ts')
.pipe(sourcemaps.init()) // This means sourcemaps will be generated
.pipe(ts({
sortOutput: true,
// ...
}));
return tsResult
.pipe(concat('lib/js-library.js')) // You can use other plugins that also support gulp-sourcemaps
.pipe(uglify())
.pipe(sourcemaps.write()) // Now the sourcemaps are added to the .js file
.pipe(gulp.dest('release/'));
});
And now, run gulp compile and see the magic!
Learn this packages and build your custom task compile.