I have a folder with a bunch of javascript. I want to be able to use recent js syntax (especially await/async). But the target should compatible with most browsers.
Since these javascript files will be used standalone (will be imported in a 3rd party app as plugin), I want to respect these scheme:
src/file1.js ==> dist/file1.js
src/sub/file2.js ==> dist/sub/file2.js
...
each files should be transpiled into a es5 js file.
I'm using gulp 4 as build tool.
How to reach my goal ?
First try : use babel-gulp:
import gulp from 'gulp';
import sourcemaps from 'gulp-sourcemaps';
import babel from 'gulp-babel';
const javascript = () => {
return gulp.src('src/**/*.js')
.pipe(sourcemaps.init())
.pipe(babel({
"presets": [
["#babel/preset-env", {
"targets": {
"browsers": [">0.25%", "not ie 11", "not op_mini all"]
}
}]
]
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('dist'));
};
The build succeeds, but at runtime, it fails with ReferenceError: regeneratorRuntime is not defined
Second try, using browserify and #babel/polyfill, inspired from Browserify + Globs (multiple destination)
Added require("#babel/polyfill"); at top of my javascript files.
in gulp file:
const javascript2 = () => {
return gulp.src('src/**/*.js', {
read: false
}) // no need of reading file because browserify does.
.pipe(tap(function(file) {
file.contents = browserify(file.path).bundle();
}))
.pipe(buffer())
.pipe(sourcemaps.init({
loadMaps: true
}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist'));
};
The build succeed, but the file is not transpiled (async keywords remain) and moreover, the whole babel polyfills are included in the output (and it's quite big) which conflicts with the target app (the app is also redefining startsWith function).
It looks like you are trying to set up a development environment. I would suggest using webpack instead of gulp, 'cause it's more relevant these days. Here's the guide I used to set one up: https://www.valentinog.com/blog/webpack-tutorial/.
Related
TL;DR
(vue files) + background.ts => ...[webpack]... => (bundled vue files) + background.js
can't execute background.js
expected background.js to contain only "console.log('test');"
I have a vue project with webpack and typescript.
I want my build step to produce a "background.js" file aside from the [vue JS related files].
I have a source file in typescript: "background.ts".
Through the vue.config.js I added a webpack entry "background".
It does build a file "background.js" as I expected
but it is bundled(I think) and it can't be executed by a chrome plugin.
For now all I want is to have a "background.js" file which execute the "console.log('test');" instruction it contains when the script is called.
Thank you, webpack is hell
edit: adding files:
// vue.config.js
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
filenameHashing: false,
chainWebpack: config => {
// add your custom entry point
config
.entry('background')
.add('./src/background.ts');
},
configureWebpack: {
plugins: [
new CopyWebpackPlugin([
{ from: 'manifest.json', to: 'manifest.json', flatten: true },
]),
]
}
}
content of "$vue inspect"
$vue inspect > https://pastebin.com/6F3zwLhC
What I tried:
exporting a function instead of my plain code:
export default function() {
console.log("gboDebug: background.ts dans export function");
}
// instead of just
console.log("gboDebug: background.ts dans export function");
at the end of the file adding this because I saw it somewhere:
export default null;
checked that my console.log was in the background.js bundled file
pasted the result of background.js in the navigator
played with the webpackJsonp global var the scripts creates
What I thought about:
having a npm script which 1-bundle-vue-webpack and then 2-transpile my file with babel-loader
playing with the library output option in webpack but I think it makes code available for use in a variable, it doesn't auto-execute code when loaded
webpack output in IIFE: https://webpack.js.org/configuration/output/#outputiife
In short – you don't need a bundler for transpiling a single typescript file. Just use tsc.
Specifically to this question where the Vue app is used as part of chrome extension, it may make sense to separate building an app and the extension related files.
Another possible option is to use something like Vue CLI Browser Extension Plugin.
I use Gulp to merge a few javascripts as well as uglify them. When I tried to do it with countUp (can be other script as well) I've got an error.
Uncaught SyntaxError: Unexpected token 'export'
It tries to export the javascript back to the script tag. Now my javascript file is not just one script, but many.
How can I make it work? Is there a tool to convert it to common js or maybe a better way to include it with gulp?
Script
A part of my gulp-file looks like below:
function script() {
return gulp
.src(js.src)
.pipe(concat(js.filename))
.pipe(gulp.dest(js.dest))
.pipe(uglify())
.pipe(rename({ extname: ".min.js" }))
.pipe(gulp.dest(js.dest));
}
You can use a gulp task to convert es6 modules to other types:
const babel = require('gulp-babel'),
gulp.task('es6-commonjs',['clean-temp'], function(){
return gulp.src(['app/*.js','app/**/*.js'])
.pipe(babel({ modules: 'common' }))
.pipe(gulp.dest('dest/temp'));
});
Then use this task in your gulp pipe. More info here.
I have a simple Gulp configuration to transpile my javascript with babel :
gulp.task('js_dev', function () {
var bundler = browserify({entries: ['js/index.js'], debug: true});
bundler.external('jquery');
return bundler
.transform("babelify", {presets: ["es2015"]})
.bundle()
.on('error', function (err) {
console.error(err);
this.emit('end');
})
.pipe(source('dev.js'))
.pipe(gulp.dest(jsdest));
});
With this, I can import my development files.
But I can't import some package installed with npm (isotope, textfit, babel-polyfill...).
For example, if I import babel-polyfill in my index.js file :
import "babel-polyfill";
No errors with gulp, and the code seems to be added in dev.js, but it's not working, and I can't require it either : it gives an empty Object.
Same things for other npm modules (isotope for example). When I require them, it just gives an empty object. And Isotope is supposed to work with require.
Any idea what's happening ?
Thanks.
Alright, I found it.
My JavaScript files were added to a CMS which already used AMD/Require.js. This conflicts with browserify.
The solution was here.
What about doing:
import BabelPolyfill from "babel-polyfill"
When I run tsc, everything runs perfectly fine. However, I cannot understand how you are meant to import other typescript modules from node modules.
This is the important part of my gulp file:
gulp.task('compile-ts', ['clean'], function(){
var sourceTsFiles = [
config.allTs,
config.typings
];
var bundler = browserify({
basedir : "src",
debug : true})
.add("app.ts")
//.add("typings/tsd.d.ts")
.plugin(tsify);
return bundler.bundle()
.pipe(source("bundle.js"))
.pipe(gulp.dest("build"))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(sourcemaps.write({includeContent: false, sourceRoot: 'src'}));
});
When I use,
import {DataRepository, List} from "tsmvc";
Where tsmvc is a typescript module node module, I get cannot find module tsmvc. Atom doesn't complain and shows me intellisense, tsc doesn't complain, but tsify does.
Can anyone point me to a gulp file doing something similar or explain the process?
Here's the github repo: https://github.com/Davste93/typescript-mvc-consumer/blob/master/gulpfile.js
Prior to version 0.15.3 of tsify, it was not possible to import TypeScript files from within node_modules.
Internally, the tsify plugin creates a transform and Browserify does not transform files under node_modules for non-global transforms. In version 0.15.3 of tsify, the global option was added and can be specified as follows:
var bundler = browserify({
basedir: "src",
debug: true
})
.add("app.ts")
.plugin(tsify, { global: true });
I try to write these code
gulp.task('script', function() {
'use strict'
return gulp.src(['app.js', 'components/**/*.jsx'])
.pipe(babel())
.pipe(browserify())
.pipe(gulp.dest("dist"));
});
but it shows some error:
SyntaxError:
/Users/Zizy/Programming/learn-react-js/components/CommentBox.jsx:58
<div className="commentBox">
^
ParseError: Unexpected token
at wrapWithPluginError (/Users/Zizy/Programming/learn-react-js/node_modules/gulp-browserify/index.js:44:10)
It seems that before .pipe(browserify()) the gulp did't transform the jsx code. But if I just remove .pipe(browserify()) I find that did transform, just cannot let babel and browserify work together.
I know maybe I can use like babelify or browserify plugin for babel though, I just want figure out the reason.
gulp-browserify doesn't quite work like that. You don't give it a bunch of buffers to collect and bundle.
You give it one file—the entry file—which it passes into Browserify. Browserify checks to see what other files the entry file references, then loads those files directly from the file system, meaning that you can't modify them with gulp plugins beforehand.
So, really, if we pretend you don't want to use Babel on your source files, your gulpfile should look like this, only passing in the entry file:
gulp.task('script', function() {
'use strict'
return gulp.src('app.js')
.pipe(browserify())
.pipe(gulp.dest("dist"));
});
However, note that gulp-browserify is no longer maintained, and this is exactly why. gulp plugins aren't supposed to read directly from the file system. That's why you're supposed to use Browserify (or, in your case, Babelify) directly with vinyl-source-stream as recommended in the gulp recipes. It's more idiomatic and less confusing.
That wraps up my answer to your question, but I'd like to add: if you're using the ES2015 module syntax (and you probably should be), there's a better way to do this. Browserify wraps all your modules separately in a bunch of code to make the programmatic CommonJS API work properly, but ES2015 modules have a declarative syntax, which makes it much easier for tools to operate on them statically. There's a tool called Rollup that takes advantage of this, allowing it to produce bundles that are smaller, faster, and more minfication-friendly than Browserify's.
Here's how you might use it with gulp:
var gulp = require('gulp'),
rollup = require('rollup-stream'),
babel = require('gulp-babel'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer');
gulp.task('script', function() {
return rollup({entry: 'app.js'})
.pipe(source('app.js'))
.pipe(buffer())
.pipe(babel())
.pipe(gulp.dest('dist'));
});
Starting from Babel 6 you need to declare the presets manually, check this.
Basically, in the root of your project you need a .babelrc with the following content:
{
"presets": [ "es2015", "react" ]
}
And the corresponding npm modules in package.json:
// package.json
{
"devDependencies": {
...
"babel-preset-es2015": "^6.1.18",
"babel-preset-react": "^6.1.18",
...
}
}
Here is a sample repository with gulp, babel and browserify
Following is the code snippet
gulp.task("js", (done) => {
const bundler = browserify({ entries: paths.js.source }, { debug: true }).transform(babel);
bundler.bundle()
.on("error", function (err) { console.error(err); this.emit("end"); })
.pipe(source(paths.build.destMinJSFileName))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(uglify())
.pipe(sourcemaps.write(paths.js.destMapFolder))
.pipe(gulp.dest(paths.build.destBuildFolder));
done();
});