Make required dependencies accessable from outside of bundle - javascript

I am using Gulp and Browserify to build a TypeScript librariy which depends on some other libraries like for example jQuery via NPM. This is my current gulpfile:
var Gulp = require("gulp");
var Browserify = require("browserify");
var Buffer = require("vinyl-buffer");
var Rename = require("gulp-rename");
var Source = require("vinyl-source-stream");
var Tsify = require("tsify");
var Uglify = require("gulp-uglify");
var Manifest = require("./package.json");
Gulp.task("build-Debug", function () {
return Browserify({
debug: true,
standalone: Manifest.name
})
.add(Manifest.main)
.plugin(Tsify)
.bundle()
.on("error", function (error) { console.error(error.toString()); })
.pipe(Source(Manifest.name + ".js"))
.pipe(Buffer())
.pipe(Gulp.dest("./dist"));
});
The bundled JS-File gets included in my site and everything works fine. I am just missing one thing: on some sites, I need to define some custom JS which shouldn't get part of the library. These custom script should be able to use jQuery for instance, but it can't since it isn't accessible from outside of the bundle.
Now, I could include it again, but this does not make sense to me. So i'd like to know:
Is there a way to make all of my dependecies from package.json accessible from outside the bundle, so that I would be able to call
$("#my_id")....
in my custom client-scripts?

You can use Browserify's require method to expose modules as external requires:
return Browserify({
debug: true,
standalone: Manifest.name
})
.add(Manifest.main)
.require("some-module") // Some module in node_modules that you want to expose.
.plugin(Tsify)
.bundle()
...
You'd obtain the module in a <script> element like this:
<script>
var someModule = require("some-module");
/* ... */
</script>
To verify that this does in fact work, you could test it with the following files:
build.js
const browserify = require("browserify");
const path = require("path");
browserify("app.js")
.require("jquery")
.bundle()
.pipe(process.stdout);
app.js
const jquery = require("jquery");
console.log("Hello, world.")
index.html
<!doctype html>
<html>
<head>
<title>so-41095676</title>
</head>
<body>
<script src="./bundle.js"></script>
<script>
console.log(require("jquery"));
</script>
</body>
</html>
Create the files in a directory and run these commands:
npm install browserify jquery
node build.js > bundle.js
Then open index.html and you should see the jQuery function logged to the console.

Related

How to use js-cookie in a standalone *.js script?

I am using gulp to concatenate and minify a number of standalone *.js scripts used on my web site. Basically this is just a catchall folder where I place little utility scripts that run on page load. For example, one of them starts a carousel slider, another adds a class to the header that shrinks it on scroll, etc. Each of these "features" has its own standalone *.js file.
Now, I would like to use the popular js-cookie library in one of those scripts. Unfortunately, since my project is not set up as an ES6 module, I am not able to able to import the js-cookie library the way it's specified in the docs, like this:
import Cookies from 'js-cookie'
When I do this, I get the error message Uncaught SyntaxError: Cannot use import statement outside a module.
I tried changing it to this:
window.Cookies = require('js-cookie')
but that gave me this error:
Uncaught ReferenceError: require is not defined
Here is my gulpfile, followed by the feature.js script in which I'm trying to use the js-cookie library:
gulpfile.js
// Initialize modules
const { src, dest, watch, series, parallel } = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
const postcss = require('gulp-postcss');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
var replace = require('gulp-replace');
var merge = require('merge-stream');
// File paths (note that src paths are arrays)
const files = {
scssSrcPath: [
'scss/*.scss',
'scss/_pageContentModules/*.scss'
],
jsSrcPath: [
'js/*.js',
'node_modules/slick-carousel/slick/slick.js'
],
scssDstPath: '../web/css',
jsDstPath: '../web/js'
}
// Sass task: compiles SCSS files into style.css
function scssTask(){
return merge(files.scssSrcPath.map(function (file) {
return src(file)
}))
.pipe(sourcemaps.init()) // initialize sourcemaps first
.pipe(sass()) // compile SCSS to CSS
.pipe(postcss([ autoprefixer(), cssnano() ])) // PostCSS plugins
.pipe(sourcemaps.write('.'))
.pipe(dest(files.scssDstPath));
}
// JS task: concatenates and uglifies JS files to script.js
function jsTask(){
return merge(files.jsSrcPath.map(function (file) {
return src(file)
}))
.pipe(concat('app.js'))
.pipe(uglify())
.pipe(dest(files.jsDstPath));
}
// Watch task: watch SCSS and JS files for changes
// If any change, run scss and js tasks simultaneously
function watchTask(){
watch(files.scssSrcPath, scssTask);
watch(files.jsSrcPath, jsTask);
}
// Export the default Gulp task so it can be run
// Runs the scss and js tasks simultaneously
// then watch task
exports.default = series(
parallel(scssTask, jsTask),
watchTask
);
js/feature.js
import Cookies from 'js-cookie';
const rs = cookies.get('referral_source');
if (typeof rs !== 'undefined') {
console.log('referral_source = ' + rs);
}
How can I get this working? Is there a way to do it using my simple Gulp setup, or do I need to go beyond and set up a full-on Webpack setup (with all the complexity that adds)?
Unfortunately, as far as I know, Gulp does not support the ability to use ES6 modules. If you want to use them, you will need to use Webpack.
But js-cookie does have a jsDelivr CDN: <script src="https://cdn.jsdelivr.net/npm/js-cookie#3.0.1/dist/js.cookie.min.js"></script>. By including this before your JS script, like this:
<script src="https://cdn.jsdelivr.net/npm/jscookie#3.0.1/dist/js.cookie.min.js"></script>
<script src="./js/feature.js"></script>

Using grunt for building prod/dev environment on frontend app

My application is currently only a frontend and I use grunt to do the following:
copy the necessary CSS and JS from bower_components into the right directories
run jshint
build documentation
I'd like to go a bit deeper into the deployment process by compiling my Handlebars templates, compiling the requirejs modules and minifying the resulting JS and all my CSS.
The problem is that I'd like to keep a development environment where the files arent't minified and the requirejs are not compiled.
How can I achieve this?
Specifically, should I template my index.html so that it uses either a single CSS for the prod environment and the multiple CSS for the dev env?
Here is the link to my sources: https://github.com/lilorox/darts/tree/dev (dev branch is the most recent).
I used to try using grunt, but when the configuration is getting bigger, I found myself pretty confused by the configuration over the grunt. I'd try to give a suggestion by using gulp for your front-end building tools. It's much simple, easier to read and faster. You can read the differences here.
Pretty much the same, while grunt specified all the configuration in gruntfile.js, gulp specified its configuration in gulpfile.js. Usually I would created my own configuration in extra file which I named gulpfile.config.js. It would looks like this :
gulpfile.config.js
module.exports = {
development: {
css: [
'./development/bower_components/bootstrap/dist/css/bootstrap.min.css',
'./development/bower_components/font-awesome/css/font-awesome.min.css'
],
js: [
'./development/bower_components/angular/angular.min.js',
'./development/app/components/*.js',
'./development/app/components/**/*.js'
],
ENV: {
name: 'development'
}
},
production: {
css: ['./production/dist/css/app.min.css'],
js: ['./production/dist/js/app.min.js'],
ENV: {
name: 'production'
}
}
}
And in gulpfile.js, I can simply run the task based on the environment that I've configured in gulpfile.config.js
var config = require('./gulpfile.config.js'),
gulp = require('gulp'),
cleancss = require('gulp-clean-css');
gulp.task('scripts', function() {
return gulp.src(config.development.js)
.pipe(concat('app.js'))
.pipe(ngannotate())
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest(config.ENV.name + '/dist/js'))
});
Just like grunt, gulp offers abundant of cool plugins for building your front-end apps. I myself usually use gulp-less, gulp-minify-css, gulp-ng-annotate, gulp-uglify, gulp-concat, gulp-server-livereload, gulp-rename, gulp-inject, gulp-imagemin. And of course you can explore much other plugins. Hope this helps!
[UPDATED - Build index.html based on environment]
First you need to configure the task and require all gulp plugins
var config = require('./gulpfile.config.js'),
gulp = require('gulp'),
del = require('del'),
inject = require('gulp-inject'),
rename = require('gulp-rename'),
gulpif = require('gulp-if'),
argv = require('yargs').argv;
if (argv.production) {
var selectedConfig = config.production;
} else {
var selectedConfig = config.development;
}
gulp.task('index', function() {
return gulp.src('./development/assets/templates/index.tpl.html')
.pipe(inject(gulp.src(selectedConfig.css.concat(selectedConfig.js), {read: false}), {ignorePath: selectedConfig.ENV.name}))
.pipe(rename('index.html'))
.pipe(gulp.dest(selectedConfig.ENV.name));
})
And provide the index.tpl.html
<!DOCTYPE html>
<html>
<head>
<!-- inject:css -->
<!-- endinject -->
</head>
<body>
<!-- inject:js -->
<!-- endinject -->
</body>
</html>
Then you can simply build the index.html by running gulp index --development or gulp index --production

Require another file in gulpfile (which isn't in node_modules)

I've been using gulp for a while now and know how to import another node module, e.g.
var sass = require('gulp-sass');
That's fine, but my gulpfile is filling up with code that I'd like to move into a separate file and "require". Specifically I am writing a postcss plugin, which I already have working when declared as a function inside of the gulpfile. My question is how to put my function in an external file and require it like I do a node module. Do I need to "export" the function in the file being required? Do I need to use ES6 modules or something like that?
As an aside, I realise that if i was doing this probably I would either (A) turn this into a proper node module and put it on a private NPM repository, but that seems unnecessary, or (B) turn it into a proper gulp plugin, but that would require learning how to author a gulp plugin and learning about streams and stuff. Both of these are probably better but would take more time so I've decided to just keep the function simple and local for now.
First create a new js file (here ./lib/myModule.js):
//./lib/myModule.js
module.exports = {
fn1: function() { /**/ },
fn2: function() { /**/ },
}
You could also pass some arguments to your module:
// ./lib/myAwesomeModule.js
var fn1 = function() {
}
module.exports = function(args) {
fn1: fn1,
fn2: function() {
// do something with the args variable
},
}
Then require it in your gulpfile:
//gulpfile.js
var myModule = require('./lib/myModule')
// Note: here you required and call the function with some parameters
var myAwesomeModule = require('./lib/myAwesomeModule')({
super: "duper",
env: "development"
});
// you could also have done
/*
var myAwesomeModuleRequire = require('./lib/myAwesomeModule')
var myAwesomeModule = myAwesomeModuleRequire({
super: "duper",
env: "development"
});
*/
gulp.task('test', function() {
gulp.src()
.pipe(myModule.fn1)
.pipe(myAwesomeModule.fn1)
.gulp.dest()
}
First, you have to add export default <nameOfYourFile> at the end of your file
Then to use it, write import gulp from 'gulp'
If you have an error message, install babel-core and babel-preset-es2015 with NPM, and add a preset "presets": ["es2015"] in your .babelrc config file.
I fix my problem by install:
npm i babel-plugin-add-module-exports
Then i add "plugins": [["add-module-exports"]] to the .babelrc

How to use gulp to minify all the js of angular

So I have installed gulp in my angular project, this is my gulpfile.js at the moment:
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var templates = require('gulp-angular-templatecache');
var minifyHTML = require('gulp-minify-html');
// Minify and templateCache your Angular Templates
// Add a 'templates' module dependency to your app:
// var app = angular.module('appname', [ ... , 'templates']);
gulp.task('templates', function () {
gulp.src([
'./**/*.html',
'!./node_modules/**'
])
.pipe(minifyHTML({
quotes: true
}))
.pipe(templates('templates.js'))
.pipe(gulp.dest('tmp'));
});
// Concat and uglify all your JavaScript
gulp.task('default', ['templates'], function() {
gulp.src([
'./**/*.js',
'!./public/js/**/*.js',
'!./node_modules/**',
'!./gulpfile.js',
'!./dist/all.js'
])
.pipe(concat('all.js'))
.pipe(uglify())
.pipe(gulp.dest('dist'));
});
When I run gulp default, everything succeeds. But how can I notice this exactly? I don't get the feeling that anything has changed, my js files still look the same.
This is my project structure:
As your gulp configuration specifies, you would have obtained a file named all.js inside your dist/ directory. This is the file that would contain your all *.js files minified code.
You should be including this inside your index.html
Your original js files are untouched. There is template.js under "tmp" folder and all.js under "dist" folder. Those files are minimized.
you can use
gulp build
that will give you a minified js inside a dist.zip
more info click here

Make browserify modules external with Gulp

I have a library lib.js that I want to create from lib/a.js and lib/b.js and to be able to use it from a script client.js using var a = require('lib/a.js'); and that it works when I just include the compiled lib.js library before client.js (therefore, lib.js has to declare a require function that knows about lib/a.js)
I guess I have to use external and alias but I am not sure what is the proper way to do it
Also, is it possible to have a Gulp file that creates all the alias automatically for the folders in my library? eg. creates an alias for all the files in the lib/ dir?
Here are a couple of gulp tasks that would help to build your common lib.js and the client.js bundles separately.
Note that you have to tell browserify to b.require() lib/*.js when bundling lib.js, and you have to tell it to b.external() the libraries that will be loaded separately when bundling client.js
var path = require('path');
var gulp = require('gulp');
var browserify = require('browserify');
var concat = require('gulp-concat');
var transform = require('vinyl-transform');
gulp.task('build-lib', function () {
// use `vinyl-transform` to wrap around the regular ReadableStream returned by b.bundle();
// so that we can use it down a vinyl pipeline as a vinyl file object.
// `vinyl-transform` takes care of creating both streaming and buffered vinyl file objects.
var browserified = transform(function(filename) {
// basename, for eg: 'a.js'
var basename = path.basename(filename);
// define the exposed name that your client.js would use to require();
// for eg: require('lib/a.js'); // -> exposed name should be 'lib/a.js'
var expose = 'lib/' + basename;
return browserify(filename)
.require(filename, { expose: expose})
.bundle();
});
return gulp.src(['./lib/*.js'])
.pipe(browserified)
.pipe(concat('lib.js'))
.pipe(gulp.dest('./dist'));
});
gulp.task('build-client', function () {
var browserified = transform(function(filename) {
// filename = './client.js'
// let browserify know that lib/a.js and and lib/b.js are external files
// and will be loaded externally (in your case, by loading the bundled lib.js
// for eg: <script src='dist/lib.js'>)
return browserify(filename)
.external('lib/a.js')
.external('lib/b.js')
.bundle();
});
return gulp.src(['./client.js'])
.pipe(browserified)
.pipe(gulp.dest('./dist'));
});
gulp.task('default', ['build-lib', 'build-client']);
Are you looking for external requires?
To use with gulp-browserify, check the README
.on('prebundle', function(bundle) {
bundle.external('domready');
bundle.external('react');
})
Should work with bundle.require as well.

Categories

Resources