Can Watchify pick up changes to html files? - javascript

I import html template files into my javascript components using babel-plugin-transform-html-import-to-string.
When I use watchify, it doesn't update if an html has been changed. Only Javascript file changes. The npm script goes something like this:
watchify -p browserify-hmr -t [babelify ext .js .html] src/index.js -o public/bundle.js
Since this doesn't work I am using watch instead, as shown below, but my builds are at least 5 seconds slower than before, when they were instant.
watch 'npm run browserify' src/ -d --interval=1
where the browserify script is
browserify -t [babelify ext .js] src/index.js -o public/bundle.js
Anyone know how I can run browserify on html file changes without sacrificing fast rebuilds?

The problem is that browserify never sees the references to the .html files, as babelify is replacing them with variables and HTML strings.
If you want watchify to watch the .html files and to rebuild the bundle if they change, you should allow babelify to transpile statements like import some from './some.html' to var some = require('./some.html') and should use a browserify-based transform (like stringify) to transform the required content:
watchify \
-p browserify-hmr \
-t [babelify ext .js] \
-t [stringify ext .html] \
src/index.js -o public/bundle.js
Browserify/watchify will then see the .html files as being included in the bundle and will watch them for changes.

Related

How do I compile TypeScript code into a single .js file, executable via "node mycode.js"?

I'd like to be able to do this without webpack, gulp, etc, just "tsc [args] mycode.ts". Is that even possible?
In my package.json, I have a build command like this:
"build:mycode": "tsc --allowSyntheticDefaultImports --lib es2018 --lib dom -m amd -t es2018 --moduleResolution node --outFile ./mycode.js ./mycode.ts",
(The reason all of the above config is done with tsc command line arguments, instead of being set up in tsconfig.json, is that I'm generating a build script that's apart from my main project, which does use tsconfig.json, webpack, etc.)
I tried to use -m commonjs, but that's not allowed with --outFile, only amd or system.
The problem is that the code generated this way produces this error when invoked by node:
ReferenceError: define is not defined
I can't figure out how to define define. Is there an argument to the node command that will supply the necessary definition? Everything I've googled so far invokes extra tools I'd rather avoid if possible, or is targeted at a web browser rather than creating a command-line tool.
Note: Any solution which involves a <scr ipt> tag is NOT applicable.
It is not possible to concatenate CommonJS modules to a single file using tsc's --outFile parameter. See https://github.com/microsoft/TypeScript/issues/7252 for a discussion.
You will need to use a bundler (e.g. webpack) in order to achieve your goal.
Original answer:
When compiling a single file using tsc, the --outFile argument is not needed. Also, the --lib option accepts either one arg, or a (comma-separated) list. Here's a modified version of your example:
tsc \
--allowSyntheticDefaultImports \
--lib es2018,dom \
--module commonjs \
--target es2018 \
--moduleResolution node \
./script.ts
This will not bundle your script, but merely transpile it to JavaScript. It will still rely on any external imports.
Here's a simple script that I made. It should work well for your use case
#!/bin/sh
SRCDIR=src
OUTDIR=build
pre_clean(){
if [ -f build/index.js ];
then
rm build/index.js
fi
}
pre_clean
mkdir -p tmp
mkdir -p $OUTDIR
tsc $SRCDIR/*.ts --outDir tmp
cd tmp
for file in *.js
do
echo "// $file " >> ../$OUTDIR/index.js
echo "" >> ../$OUTDIR/index.js
cat $file >> ../$OUTDIR/index.js
# sed 1,2d $file >> ../$OUTDIR/index.js
echo "" >> ../$OUTDIR/index.js
done
# Cleanup
cd ..
rm -r tmp
# Add package.json
sed s:build/index.js:index.js:g package.json > build/package.json
cp package-lock.json build
true

Use Babelify with Browserify Globally / Global in WebStorm

Background:
I have several vanilla JS projects with files up to 25 000 lines / single file in which I would like to use ES6 capabilities + require so I can make the code more readable. OS X guy by the way
Possible solution:
I could make up a package.json and use a webpack for each project, but I would prefer if I do not do that.
What I have done so far:
Install browserify globally
sudo npm install -g browserify
setup a watcher in PhpStorm
global browserify path
/usr/local/lib/node_modules/browserify/bin/cmd.js
arguments
$FilePath$
-o
$FileDir$/$FileNameWithoutAllExtensions$.js
all works fine, and if I have a require in my code
var foo = require('./inc/_dependency-functionality');
✅ it will bundle just right and the required external files will get bundle inside a single file
BUT, ideally, I would like to have it so that I can use ES6 import / export functions, which may say I need babelify
doing this
sudo npm install -g browserify
and using
$FilePath$
-o
$FileDir$/$FileNameWithoutAllExtensions$.js
-t [ /usr/local/lib/node_modules/babelify --presets [/usr/local/lib/node_modules/#babel/preset-env ] ]
❌ will not actually babelify the script
I'm kind of stuck
Ok, I managed to do it
$FilePath$
-o
$FileDir$/$FileNameWithoutAllExtensions$.js
-t [ /usr/local/lib/node_modules/babelify/index.js --presets [/usr/local/lib/node_modules/#babel/preset-env ] ]
Babelify should be appended by /index.js
and then you can actually lose the presets, if you have .babelrc in the home of your user library ( babel searches for .babelrc recursively on top )
$FilePath$
-o
$FileDir$/$FileNameWithoutAllExtensions$.js
-t [ /usr/local/lib/node_modules/babelify/index.js ]
Also, make sure your files are named file.source.js not file.babel as I had them, as the transpiling will not start for unknown files

How to manually bundle two javascript files?

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

bundle a large node.js application into a single .js file

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.

How to minify and factor-bundle files in the same browserify command?

I currently have this factor-bundle command which I use to bundle my files, and pull everything common into a common file:
browserify index.js bar-charts.js list-filter.js dashboard.js
-p [ factor-bundle -o ../../static/js/index.js -o ../../static/js/bar-chart.js -o ../../static/js/list-filter.js -o ../../static/js/dashboard.js ]
-o ../../static/js/common.js
I previously also used this command to uglify individual files:
browserify index.js | uglifyjs > ../../static/js/index.min.js
How can I both combine files with factor-bundle, and minify them with uglifyjs, in the same command?
I found this example in the factor-bundle docs, but I don't really understand how to adapt it.
(I could also use two commands, if that works better. I just want to end up with minified and combined files!)
I happened to have been looking into this area recently and stumbled on what I think might be able to help you.
browserify files/*.js \
-p [ ../ -o 'uglifyjs -cm | tee bundle/`basename $FILE` | gzip > bundle/`basename $FILE`.gz' ] \
| uglifyjs -cm | tee bundle/common.js | gzip > bundle/common.js.gz
I've not dabbled much with browserify but to me this looks as though it is simply piping the output from factor-bundle into uglify.
source: https://gist.github.com/substack/68f8d502be42d5cd4942
Hope this helps someone

Categories

Resources