browserify and reactify multiple source and destination files - reactjs

I'm converting my project from Grunt to Gulp, and have multiple input jsx and output js files. I'm trying to write a [simple] task that'll correctly combine the sources into separate app files. The directory structure is this:
├── dist
│   └── js
│   ├── app1.js
│   └── app2.js
└── src
├── app1.jsx
├── app2.jsx
└── components
├── Button.jsx
├── Dashboard.jsx
├── Item.jsx
├── List.jsx
└── Widget.jsx
Where app1.jsx loads some components and app2.jsx loads different ones. For example:
app1.jsx
var Button = require('./components/Button');
var List = require('./components/List');
var Item = require('./components/Item');
// etc
app2.jsx
var Button = require('./components/Button');
var Dashboard = require('./components/Dashboard');
var Widget = require('./components/Widget');
var List = require('./components/List');
// etc ...
Different app files will be used in different pages, and components will be shared between requiring apps.
So the idea is to run a task that'll run through the requirements for the different app files and compile the outputs using browserify and reactify to separate files unders dist/js/. I got it to work up to the react part using gulp-react, but handling the browserification part proved tricky - here's my gulpfile.js:
var react = require('gulp-react');
var browserify = require('browserify');
var transform = require('vinyl-transform');
var del = require('del');
var browserified = transform(function(filename) {
var b = browserify();
return b.bundle();
});
gulp.task('clean', function() {
del.bind(null, ['dist']);
});
gulp.task('react', ['clean'], function() {
return gulp.src(['src/*.jsx'])
.pipe(react())
.pipe(browserified)
.pipe(gulp.dest('dist'));
});
This generates dist/js/{app1,app2}.js, but they only contain the JS code that defines the require(..) functionality, without the reactified source. If I remove the .pipe(browserified) statement, the files contain the correct reactified code, but don't load and requirements.
I would appreciate some pointers on what I'm doing wrong. thanks.

I think the problem is your path in:
gulp.task('react', ['clean'], function() {
return gulp.src(['src/*.jsx']) // here!
.pipe(react())
.pipe(browserified)
.pipe(gulp.dest('dist'));
});
You are compiling app1.jsx and app2.jsx but not the components/*.jsx files. You can use globbing-patterns to fix it:
gulp.task('react', ['clean'], function() {
return gulp.src(['src/**/*.jsx']) // here!
.pipe(react())
.pipe(browserified)
.pipe(gulp.dest('dist'));
});
Hope it helps :)

Related

how to force webpack to load umd bundle of a library

I'm writing an angular1 + angular2 hybrid application which uses webpack as package bundler.
In my code I import a library (#angular/upgrade) in this way
import { UpgradeModule } from '#angular/upgrade/static';
Angular upgrade library is sitting in node_module folder with the following tree structure (simplified):
#angular/upgrade
├── bundles
│   ├── upgrade-static.umd.js
│   ├── upgrade-static.umd.min.js
│   ├── upgrade.umd.js
│   └── upgrade.umd.min.js
├── index.d.ts
├── index.js
├── index.js.map
├── index.metadata.json
├── package.json
├── static
│   └── package.json
├── static.d.ts
├── static.js.map
├── static.metadata.json
└── static.js
The problem is that by default webpack resolve my import statement loading #angular/upgrade/static.js, an ES6 file which, once bundled with the rest of the code generate errors.
What I'd like webpack to do instead is loading #angular/upgrade/static/package.json which contains the right main definition pointing to the umd bundle
{"main": "../bundles/upgrade-static.umd.js"}
Is that achievable?
Thanks,
Gab
Although the module resolution described here:
https://webpack.github.io/docs/resolving.html
should be able to do what I've described above by default, in order to achieve that I had to use the resolve.alias property. Here's the configuration that I've used:
resolve: {
extensions: [ '.js', '.ts', '' ],
modulesDirectories: [ path.resolve( __dirname, 'node_modules' ) ],
alias: {
'#angular/upgrade/static$': '../../node_modules/#angular/upgrade/bundles/upgrade-static.umd.js'
}
},
Does import UpgradeModule from '#angular/upgrade/bundles/upgrade-static.umd.js'; work?
Webpack only follows the main in package.json if package.json is at the root level of the npm module, so in this case you'll have to access the file you want directly.

Nativescript angular Cannot move app.component.html in to separte folder

I am using nativescript 2.3.0 with angular. I created a starter project with the following command
tns create projname --ng
I have the following folder structure
├── app
│ ├── app.css
│ ├── app.component.html
│ ├── app.component.ts
│ ├── main.ts
In side the main.ts file i have the following.
import { platformNativeScriptDynamic, NativeScriptModule } from "nativescript-angular/platform";
import { NgModule } from "#angular/core";
import { AppComponent } from "./app.component";
#NgModule({
declarations: [AppComponent],
bootstrap: [AppComponent],
imports: [NativeScriptModule]
})
class AppComponentModule {}
platformNativeScriptDynamic().bootstrapModule(AppComponentModule);
Notice that I am importing the AppComponent on line 3
What I want to do is that I want to organize my code so that i have the app.component file in a separate folder
As shown below
│ ├── pages
│ │ └── app.component.ts
│ │ └── app.component.html
│ ├── app.css
│ ├── main.ts
I have changed the import in main.ts file to follows
import { AppComponent } from "./pages/app.component";
Moving the file app.component.html file give the following error.
Unhandled Exception
com.tns.nativescriptException:
Calling js method onCreateView failed

Gulp not including all javascript files

I am developing a web application using the MEAN framework and gulp for minification of the files. However, the application does not work because there are lots of "is not a function, got undefined" when I inspect the navigator console. When I read the app.min.js file which is generated with gulp, I can't find most of javascripts files (controllers, services and so on).
The folder structure that I am using for the client is the following:
client/
├── app.min.js
├── app.min.js.map
├── controllers
│   ├── auth
│   │   ├── login_controller.js
│   │   └── register_controller.js
│   ├── home
│   │   └── home_controller.js
│   ├── navigation
│   │   └── navigation_controller.js
│   └── profile
│   └── profile_controller.js
├── directives
│   └── navigation.js
├── index.html
├── main.js
├── services
│   ├── authentication.js
│   └── data.js
└── views
├── auth
│   ├── login
│   │   └── login.html
│   └── register
│   └── register.html
├── home
│   └── home.html
├── navigation
│   └── navigation.html
└── profile
└── profile.html
This the the gulp file which I am using:
var gulp = require("gulp");
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
var watch = require("gulp-watch");
var sourcemaps = require("gulp-sourcemaps");
var ngHtml2Js = require("gulp-ng-html2js");
gulp.task("scripts", function() {
gulp.src([
"./client/**/*.js",
"!./client/app.min.js"
]).pipe(sourcemaps.init())
.pipe(concat("./app.min.js"))
.pipe(uglify({mangle: true}))
.pipe(gulp.dest("client"))
.pipe(sourcemaps.write("./"))
.pipe(gulp.dest("client"));
});
gulp.task("watch", function() {
watch(["./client/**/*.js", "!./client/**/*.test.js", "!./client/app.min.js"], function() {
gulp.start("scripts");
});
});
gulp.task("default", ["scripts", "watch"]);
Thanks in advance.
EDIT:
This is the generated app.min.js file:
!function(){function t(t,e){t.when("/",{templateUrl:"views/home/home.html",controller:"homeCtrl",controllerAs:"vm"}).when("/register",{templateUrl:"views/register/register.html",controller:"registerCtrl",controllerAs:"vm"}).when("/login",{templateUrl:"views/login/login.html",controller:"loginCtrl",controllerAs:"vm"}).when("/profile",{templateUrl:"views/profile/profile.html",controller:"profileCtrl",controllerAs:"vm"}).otherwise({redirectTo:"/"}),e.html5Mode(!0)}function e(t,e,n){t.$on("$routeChangeStart",function(t,o,r){"/profile"!==e.path()||n.isLoggedIn()||e.path("/")})}angular.module("app",["ngRoute"]),angular.module("app").config(["$routeProvider","$locationProvider",t]).run(["$rootScope","$location","authentication",e])}(),function(){function t(){return{restrict:"EA",templateUrl:"/views/navigation/navigation.html",controller:"navigationCtrl as navvm"}}angular.module("app").directive("navigation",t)}(),function(){function t(t,e){var n=function(t){e.localStorage["token"]=t},o=function(){return e.localStorage["token"]},r=function(){var t,n=o();return n?(t=n.split(".")[1],t=e.atob(t),t=JSON.parse(t),t.exp>Date.now()/1e3):!1},i=function(){if(r()){var t=o(),n=t.split(".")[1];return n=e.atob(n),n=JSON.parse(n),{email:n.email,name:n.name}}},l=function(e){return t.post("/api/register",e).success(function(t){n(t.token)})},a=function(e){return t.post("/api/login",e).success(function(t){n(t.token)})},c=function(){e.localStorage.removeItem("token")};return{currentUser:i,saveToken:n,getToken:o,isLoggedIn:r,register:l,login:a,logout:c}}angular.module("app").service("authentication",t),t.$inject=["$http","$window"]}(),function(){function t(t,e){var n=function(){return t.get("/api/profile",{headers:{Authorization:"Bearer "+e.getToken()}})};return{getProfile:n}}angular.module("app").service("appData",t),t.$inject=["$http","authentication"]}(),function(){function t(t,e){var n=this;n.credentials={name:"",email:"",password:""},n.onSubmit=function(){console.log("Submitting registration"),e.register(n.credentials).error(function(t){alert(t)}).then(function(){t.path("profile")})}}angular.module("app").controller("registerCtrl",t),t.$inject=["$location","authentication"]}(),function(){function t(){console.log("Home controller is running")}angular.module("app").controller("homeCtrl",t)}(),function(){function t(t,e){var n=this;n.user={},e.getProfile().success(function(t){n.user=t}).error(function(t){console.log(t)})}angular.module("app").controller("profileCtrl",t),t.$inject=["$location","appData"]}();
//# sourceMappingURL=app.min.js.map

TSIFY compatibility with Typescript AngularJS

I am trying to build a gulp based process that would use AngularJS from a bower package and a tool called debowerify (which I believe should let me plug in the installed bower components into the TSIFY/Browserify stream). Essentially, I want to build an app.js file for use in my application (with all the JS I need). I cannot for the life of me get AngularJS to work in this process. I am using an index.ts file (see below) to bring in my references for browserify to work with. It has been tricky with angular as the library is optimized out by the compilation process unless you use the import in some way hence the module call I was testing in the index.ts file.
index.ts
//#### Type Definitions ####
/// <reference path="../../typings/angularjs/angular.d.ts" />
/// <reference path="greeter.ts" />
import angular = require('angular');
import greeter = require('./Greeter');
var greet = new greeter();
greet.sayHello();
angular.module('app', []);
Here are my gulp defintions:
gulpfile.js
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var browserify = require('browserify');
var tsify = require('tsify');
var debowerify = require('debowerify');
var exorcist = require('exorcist');
var config = {
publicDir: __dirname + '/app',
path: __dirname + '/src/typescript',
main: 'index.ts',
result: 'app.js'
};
gulp.task('compile-ts', function(){
var bundler = browserify({
basedir: config.path,
debug: true
})
.add(config.path + '/' + config.main)
.plugin(tsify)
.transform(debowerify);
return bundler.bundle()
.pipe(exorcist(config.publicDir + '/app.js.map'))
.pipe(source(config.result))
.pipe(gulp.dest(config.publicDir));
});
The custom TS files I built (ie: greeter.ts) work great. However, when I run my gulp compile-ts task I get no errors in the console only in the browser when it informs me that angular is undefined (on the call to angular.module). I have suspicions that CommonJS may not be supported for angular, but I also found information on the interwebs to the contrary of that. I am trying to avoid AMD if possible but if that is my only option I would certainly re-consider. I have this application working if I link to the angular script in my html rather than attempt to import it into my typescript, but I am just not satisfied with that approach as I know this should work.
Angular doesn't currently support CommonJS, replacing
import angular = require('angular');
with
require('angular');
solved it for me. See here.

ideal code/folder structure for CRUD app

As part of learning angular i’ve decided to create a simple bug tracker app using ng-boilerplate as a starting point as I like their approach to folder structure. I’ve got the auth down and have moved onto the "members area” which lists all the users projects and allows them to create new projects and to eventually add bugs to each project.
I’m having a bit of an analysis paralysis in regards to structuring the code the “angular way”. So far I have :
- member
— add-project
—— add.js
—— add.tpl.html
- member.tpl.html
- member.js
inside member.js I have a memberctrl which lists the users projects and adds a new project, calling a factory called ProjectsService (also sitting in member.js) to do both. The ProjectsService currently has two methods, query() and add() although obviously this would grow to include update, delete etc.
The add.js in the add-project folder seems a bit redundant at the moment, but i’m worried that the member controller is going to grow (editing projects, adding bugs, editing bugs etc) so what would be an ideal structure going forward? Should I have a separate addProjectCtrl inside add.js solely for adding a project? Should I remove add() from ProjectsService and move it into its own factory in add.js as well?
Code for member.js is as follows
.controller('MemberCtrl', function MemberCtrl($scope, $location,ProjectsService) {
$scope.projects = [];
$scope.refresh = function () {
ProjectsService.query()
.then(function (data) {
$scope.projects = data;
});
};
$scope.addProject = function (project) {
ProjectsService.add(project).then(function (data) {
$scope.projects = data;
$location.path("/member");
});
};
//is this just going to get bigger and bigger?
$scope.refresh();
})
.factory('ProjectsService', ['$http', '$q', function ($http, $q) {
return {
query: function () {
var deferred = $q.defer();
$http.get('/api/get-projects')
.success(function (data) {
deferred.resolve(data);
})
.error(function (data) {
deferred.reject(data);
});
return deferred.promise;
},
add: function (project) {
var deferred = $q.defer();
$http.post('/api/create-project', project)
.success(function (data) {
deferred.resolve(data);
})
.error(function (data) {
deferred.reject(data);
});
return deferred.promise;
}
};
}])
and code for add.js
angular.module( 'ngBoilerplate.member.add-project', [
'ui.router',
'placeholders',
'ui.bootstrap',
'ngBoilerplate.config',
'ngBoilerplate.member'
])
.config(function config( $stateProvider,USER_ROLES ) {
$stateProvider.state( 'member.add-project', {
url: '/add-project',
views: {
"main": {
templateUrl: 'member/add-project/add.tpl.html'
}
},
data:{ pageTitle: 'Add Project'
}
});
})
;
Take a look at the official angular-seed project, or Yeoman angular generator which will give you a barebone structure for start your angular projects.
A generally good practice is to split into different files your Controllers / Services / Directives.
For a more detailed code guide, read the popular angular-style-guide.
Extracted from it, here is an example of structure :
.
├── app
│ ├── app.js
│ ├── controllers
│ │ ├── home
│ │ │ ├── FirstCtrl.js
│ │ │ └── SecondCtrl.js
│ │ └── about
│ │ └── ThirdCtrl.js
│ ├── directives
│ │ ├── home
│ │ │ └── directive1.js
│ │ └── about
│ │ ├── directive2.js
│ │ └── directive3.js
│ ├── filters
│ │ ├── home
│ │ └── about
│ └── services
│ ├── CommonService.js
│ ├── cache
│ │ ├── Cache1.js
│ │ └── Cache2.js
│ └── models
│ ├── Model1.js
│ └── Model2.js
├── partials
├── lib
└── test

Resources