How to use Fable output to other JS projects - fable-f#

I have a small fs file code
module FableApp
open Fable.Import.Browser
let sum x y=
x+y
let myfunct=
let result=sum 5 10
console.log(result)
I am trying to compile it to JS and use in other projects. I have seen that its possible through Fable Repl but I want to do pragmatically. As I need to compile FsProjects in future.
When I tried to compile this using webpack then I got this code
(window.webpackJsonp= window.webpackJsonp|| []).push([
[0],
[function(n, o, t) {
"use strict";
function c(n, o) {
return n + o | 0
}
t.r(o), t.d(o, "Sum", function() {
return c
}), t.d(o, "myfunct", function() {
return r
});
var r = function() {
var n = 0 | c(5, 10);
console.log(n)
}()
}]
]);

According to your requirements I think that the fable-splitter npm package would be exactly the thing you are looking for.
As described in the documentation you would add a line to the scripts block of your package.json file in which you tell the script runner to build your project and put the unbundled files to the output location.
"scripts": {
"build": "fable-splitter src/MyProject.fsproj --outDir out"
}
There are more fine grained configuration options I'd suggest you look at the documentation to get acquainted with the API in case you should need it. If you want to use the configuration in your build you would change the script block to include a configuration parameter pointing to the config file.
"scripts": {
"build": "fable-splitter --config splitter.config.js"
}

Related

Gulp 3.9 to 4 Migration

I know this has been asked many times before, but none of the answers helped me to solve my problem migrating gulp 3 to 4. We didn't necessarily have to upgrade to version 4 of gulp, but updating Node.js from 10 to 12 forced us to do so, since Node.js 12 doesn't support gulp 3 anymore. Here are just 2 of files in our build process, I think that it should be enough to understand what the problem is from these files alone, but I can add the other files if need be. And I have also removed the contents of most functions for brevity.
// gulpfile.js
'use strict';
var gulp = require('gulp');
var wrench = require('wrench');
/**
* This will load all js or coffee files in the gulp directory
* in order to load all gulp tasks
*/
wrench.readdirSyncRecursive('./gulp').filter(function (file) {
return (/\.(js|coffee)$/i).test(file);
}).map(function (file) {
require('./gulp/' + file);
});
/**
* Default task clean temporaries directories and launch the
* main optimization build task
*/
//gulp.task('default', ['clean'], function () { <-- Original line, worked in gulp 3.9
function main(done)
{
gulp.start(build);
done();
}
exports.default = gulp.series(clean, main);
And another file:
// build-dev.js
'use strict';
var path = require('path');
var gulp = require('gulp');
var conf = require('./conf');
var $ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del']
});
//gulp.task('html-dev', ['inject'], function () <-- Original line, worked in gulp 3.9
function htmlDev()
{
// Removed for brevity...
}
exports.htmlDev = gulp.series(exports.inject, htmlDev); <-- this is the line that fails
//gulp.task('fonts-dev', function () <-- Original line, worked in gulp 3.9
function fontsDev()
{
// Removed for brevity...
}
exports.fontsDev = fontsDev;
//gulp.task('other-dev', function () <-- Original line, worked in gulp 3.9
function otherDev()
{
// Removed for brevity...
}
exports.otherDev = otherDev;
//gulp.task('clean', function () <-- Original line, worked in gulp 3.9
function clean()
{
// Removed for brevity...
}
exports.clean = clean;
//gulp.task('build:dev', ['html-dev', 'fonts-dev', 'other-dev']); <-- Original line, worked in gulp 3.9
exports.buildDev = gulp.series(exports.htmlDev, fontsDev, otherDev);
And when I run gulp I get the following error:
AssertionError [ERR_ASSERTION]: Task never defined: undefined
at getFunction (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\node_modules\undertaker\lib\helpers\normalizeArgs.js:15:5)
at map (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\node_modules\arr-map\index.js:20:14)
at normalizeArgs (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\node_modules\undertaker\lib\helpers\normalizeArgs.js:22:10)
at Gulp.series (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\node_modules\undertaker\lib\series.js:13:14)
at Object.<anonymous> (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\gulp\build-dev.js:61:24)
at Module._compile (internal/modules/cjs/loader.js:936:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:947:10)
at Module.load (internal/modules/cjs/loader.js:790:32)
at Function.Module._load (internal/modules/cjs/loader.js:703:12)
at Module.require (internal/modules/cjs/loader.js:830:19) {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: undefined,
expected: true,
operator: '=='
}
The error is in the second file, build-dev.js, and I indicate it in the code I provided. I have been trying to follow tutorials and SO questions, but to no avail. What gives?
OK, I apparently got it all wrong (yup, makes sense, from a guy that doesn't know either gulp 3 nor gulp 4 :)).
Since gulp 4 has some quite substantial changes, I had to actually rewrite the whole process (not the tasks themselves, they are more or less fine, except some here and there).
So basically, I changed the tasks to functions, used exports for some tasks to make them well known, and used series/parallel for the tasks' flow.
But I have another problem, related to the destination path, but that's a topic for another post.
Thanks everyone.

How do I mix promises and pipe in gulp?

In my project I compile multiple bundles from source files in nested directories using rollup.
I had a gulpfile with the following code, which worked fine:
function build_app_js(file, name) {
return gulp.src(file)
.pipe(sourcemaps.init())
.pipe(rollup({format:'iife'}))
.pipe(terser())
.pipe(rename(name + '.js'))
.pipe(rename({suffix: '.min'}))
.pipe(sourcemaps.write())
.pipe(gulp.dest(js_apps_dir))
}
// call the above for multiple sets of file+app_name
But then I changed one of the dependencies in my ES6 code which I accessed by relative path into an npm package, so it is now in node_modules. Rollup needs a plugin to resolve this, so I changed the above to this:
.pipe(rollup({plugins: [resolveNodeModules()], format:'iife'}))
However this simply does not work.
I consulted rollup's docs on gulp, and adapted the example to my case, so it now looks like this:
function build_app_js(file, name) {
return rollup.rollup({
input: file,
plugins: [
resolveNodeModules()
]
}).then(bundle => {
return bundle.write({
file: js_apps_dir + '/' + name + '.js',
format: 'iife',
sourcemap: true
});
});
}
This works, but has no minification step, and I don't know how to add one.
More generally, this is a totally different paradigm from using pipe(), and I do not know how to make both work together.
Do I try to add minification in the Promise syntax, or do I wrap the Promise function in such a way that I can use it with pipe?
Answering own question after 8 days.
Minification can be achieved via rollup plugins, such as rollup-plugin-terser.
You just need to be careful with how you import them:
var rollup = require('rollup');
var resolveNodeModules = require('rollup-plugin-node-resolve');
//var terser = require('rollup-plugin-terser'); // WRONG
var {terser} = require('rollup-plugin-terser'); // CORRECT
function build_app_js(file, name) {
return rollup.rollup({
input: file,
plugins: [
resolveNodeModules(),
terser()
]
}).then(bundle => {
return bundle.write({
file: js_apps_dir + '/' + name + '.js',
format: 'iife',
sourcemap: true
});
});
}
If you import it the wrong way, you will get a terser() is not a function type error, which is because it will have imported terser as a module.
It's a bit annoying that different rollup-plugins can't be imported the same way, but hey.

Gulp not copying Angular2 to lib-npm

I'm following this tutorial. http://www.c-sharpcorner.com/article/using-mvc-6-and-angularjs-2-with-net-core/
I have gotten to the point of using gulp to copy files to the lib-npm folder. All the expected files copy except angular. I receive no error message, the files just are there.
here is my gulp file
/// <binding />
/*
This file in the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007
*/
"use strict";
var gulp = require("gulp");
var root_path = {
webroot: "./wwwroot/"
};
//library source
root_path.nmSrc = "./node_modules/";
//library destination
root_path.package_lib = root_path.webroot + "lib-npm/";
gulp.task("copy-systemjs", function () {
return gulp.src(root_path.nmSrc + '/systemjs/dist/**/*.*', {
base: root_path.nmSrc + '/systemjs/dist/'
}).pipe(gulp.dest(root_path.package_lib + '/systemjs/'));
});
gulp.task("copy-angular2", function () {
return gulp.src(root_path.nmSrc + '/angular2/bundles/**/*.js', {
base: root_path.nmSrc + '/angular2/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/'));
});
gulp.task("copy-es6-shim", function () {
return gulp.src(root_path.nmSrc + '/es6-shim/es6-sh*', {
base: root_path.nmSrc + '/es6-shim/'
}).pipe(gulp.dest(root_path.package_lib + '/es6-shim/'));
});
gulp.task("copy-rxjs", function () {
return gulp.src(root_path.nmSrc + '/rxjs/bundles/*.*', {
base: root_path.nmSrc + '/rxjs/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/rxjs/'));
});
gulp.task("copy-all", ["copy-rxjs", 'copy-angular2', 'copy-systemjs', 'copy-es6-shim']);
I have also noticed that my .\node_modules\Angular2 folder in my project doesn't have an .js files in it. Is this normal?
Angular2 version is 1.0.2
I receive the following errors on build because the files are missing
Cannot find name 'Component'.
Build:Cannot find module 'angular2/core'.
Build:Cannot find module 'angular2/platform/browser'.
Build:Cannot find name 'Component'.
Cannot find module 'angular2/core'.
Cannot find module 'angular2/platform/browser'
I would suggest you not to copy node_modules every time you build an app. You can easily amend the UseStaticFiles middleware inside the Startup.cs class as described here. By doing this your node_modules stay where they are and you don't need to repeatedly copy them.
Btw. Recently (before switching to UseStatisFiles modification) I have done the same in the Gulp and the following has worked well:
gulp.task('build-angular-js', function () {
return gulp.src(paths.angularJs)
.pipe(cache('linting'))
.pipe(gulp.dest(paths.jsNgDest));
});
..where paths equals to:
var paths = {
webroot: "./wwwroot/",
angularJs: [
"./node_modules/core-js/client/shim.min.js",
"./node_modules/zone.js/dist/zone.js",
"./node_modules/reflect-metadata/Reflect.js",
"./node_modules/systemjs/dist/system.src.js",
"./App/External/systemjs.config.js",
"./node_modules/#angular/**/*.js",
"./node_modules/rxjs/**/*.js"
],
appJs: [
"./App/App/**/*.js"
]
};
paths.jsDest = paths.webroot + "app";
paths.jsNgDest = paths.webroot + "app";
The complete template and all sources including gulpfile.js can be found here on GitHub. Note that cache is a gulp plugin to avoid copying not modified files. As said above though - better to avoid copying node_modules.

Removing console.log from React Native app

Should you remove the console.log() calls before deploying a React Native app to the stores? Are there some performance or other issues that exist if the console.log() calls are kept in the code?
Is there a way to remove the logs with some task runner (in a similar fashion to web-related task runners like Grunt or Gulp)? We still want them during our development/debugging/testing phase but not on production.
Well, you can always do something like:
if (!__DEV__) {
console.log = () => {};
}
So every console.log would be invalidated as soon as __DEV__ is not true.
Babel transpiler can remove console statements for you with the following plugin:
npm i babel-plugin-transform-remove-console --save-dev
Edit .babelrc:
{
"env": {
"production": {
"plugins": ["transform-remove-console"]
}
}
}
And console statements are stripped out of your code.
source: https://hashnode.com/post/remove-consolelog-statements-in-production-in-react-react-native-apps-cj2rx8yj7003s2253er5a9ovw
believe best practice is to wrap your debug code in statements such as...
if(__DEV__){
console.log();
}
This way, it only runs when you're running within the packager or emulator. More info here...
https://facebook.github.io/react-native/docs/performance#using-consolelog-statements
I know this question has already been answered, but just wanted to add my own two-bits. Returning null instead of {} is marginally faster since we don't need to create and allocate an empty object in memory.
if (!__DEV__)
{
console.log = () => null
}
This is obviously extremely minimal but you can see the results below
// return empty object
console.log = () => {}
console.time()
for (var i=0; i<1000000; i++) console.log()
console.timeEnd()
// returning null
console.log = () => null
console.time()
for (var i=0; i<1000000; i++) console.log()
console.timeEnd()
Although it is more pronounced when tested elsewhere:
Honestly, in the real world this probably will have no significant benefit just thought I would share.
I tried it using babel-plugin-transform-remove-console but the above solutions didn't work for me .
If someone's also trying to do it using babel-plugin-transform-remove-console can use this one.
npm i babel-plugin-transform-remove-console --save-dev
Edit babel.config.js
module.exports = (api) => {
const babelEnv = api.env();
const plugins = [];
if (babelEnv !== 'development') {
plugins.push(['transform-remove-console']);
}
return {
presets: ['module:metro-react-native-babel-preset'],
plugins,
};
};
I have found the following to be a good option as there is no need to log even if __DEV__ === true, if you are not also remote debugging.
In fact I have found certain versions of RN/JavaScriptCore/etc to come to a near halt when logging (even just strings) which is not the case with Chrome's V8 engine.
// only true if remote debugging
const debuggingIsEnabled = (typeof atob !== 'undefined');
if (!debuggingIsEnabled) {
console.log = () => {};
}
Check if in remote JS debugging is enabled
Using Sentry for tracking exceptions automatically disables console.log in production, but also uses it for tracking logs from device. So you can see latest logs in sentry exception details (breadcrumbs).

Testing Yeoman generator with bowerInstall and/or npmInstall

I have a Yeoman generator that uses this.bowerInstall()
When I test it, it tries to install all the bower dependencies that I initialized this way. Is there a way to mock this function ?
The same goes for the this.npmInstall() function.
I eventually went with a different approach. The method from drorb's answer works if you are bootstrapping the test generators manually. If you use the RunContext based setup (as described on the Yeoman (testing page)[http://yeoman.io/authoring/testing.html]), the before block of the test looks something like this.
before(function (done) {
helpers.run(path.join( __dirname, '../app'))
.inDir(path.join( __dirname, './tmp')) // Clear the directory and set it as the CWD
.withOptions({ foo: 'bar' }) // Mock options passed in
.withArguments(['name-x']) // Mock the arguments
.withPrompt({ coffee: false }) // Mock the prompt answers
.on('ready', function (generator) {
// this is called right before `generator.run()`
})
.on('end', done);
})
You can add mock functions to the generator in the 'ready' callback, like so:
.on('ready', function(generator) {
generator.bowerInstall = function(args) {
// Do something when generator runs bower install
};
})
The other way is to include an option in the generator itself. Such as:
installAngular: function() {
if (!this.options['skip-install']) {
this.bowerInstall('angular', {
'save': true
});
}
}
finalInstall: function() {
this.installDependencies({
skipInstall: this.options['skip-install']
});
}
Now since you run the test with the 'skip-install' option, the dependencies are not installed. This has the added advantage of ensuring the command line skip-install argument works as expected. In the alternate case, even if you run the generator with the skip-install argument, the bowerInstall and npmInstall functions from your generator are executed even though, the installDependencies function is not (as it is usually configured as above)
Take a look at the tests for the Bootstrap generator, it contains an example of mocking the bowerInstall() function:
beforeEach(function (done) {
this.bowerInstallCalls = [];
// Mock bower install and track the function calls.
this.app.bowerInstall = function () {
this.bowerInstallCalls.push(arguments);
}.bind(this);
}.bind(this));

Resources