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.
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
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
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 :)
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