webpack with angular 1 and bower - angularjs

I'm building an app that uses webpack to bundle all of my javascript, node modules, and bower components. I was able to get angular and node modules working on their own, but when I tried to include my bower components I get the following error
app.bundle.js:9 Uncaught TypeError: angular.module is not a function
what my webpack build looks like
var webpack = require('webpack');
var BowerWebpackPlugin = require("bower-webpack-plugin");
module.exports = {
loaders: [
{test: /\.css$/, loader: "style!css"},
{test: /\.(woff|svg|ttf|eot)([\?]?.*)$/, loader: "file-loader?name=[name].[ext]"}
],
context: __dirname + '/web',
entry: {
app: './app.js',
vendor: ['angular']
},
resolve: {
modulesDirectories: ["web_modules", "node_modules", "bower_components"]
},
output: {
path: __dirname + '/dist/js',
filename: 'app.bundle.js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin( /* chunkName= */ "vendor", /* filename= */ "vendor.bundle.js"),
new BowerWebpackPlugin({
excludes: /.*\.less/
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
],
extensions: ['', '.json', '.js']
};
inside of my app.js (angular app declaration file) I have this
var angular = require('angular');
require("jquery");
require("bootstrap");
angular.module('App', []);
require('./services');
require('./controllers');
require('./directives');
How can I resolve this issue?
EDIT** I'm starting to think it has something to do with using the same entry point for the commonschunkplugin and the bowerwebpackplugin

In my npm-based project that uses Browserify, I had a similar issue. Then I noticed either on another discussion or in the docs it was said (paraphrasing):
do not store angular in a var as it creates issues with the global reference to angular
So instead of
var angular = require('angular');
try
require('angular');
and still call angular.module( name, []) as you normally would. My guess is that whatever returns from require('angular') is undefined or doesn't provide the angular APIs.

Related

How can I load angularjs 1.* ngRoute with webpack 4.*?

I am trying to set up a basic angularjs + webpack project. I can get it running well as long as i stick to angularjs alone (ngApp = angular.module('ngApp), [])). Whenever I try to take the step to add some angular extension (ngApp = angular.module('ngApp), ['ngRoute']) something just doesn't work. I'm fairly certain the problem is with the loading of the library. I don't want to use bower, i want to use Webpack to run it.
webpack.config.js:
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Webpack Starter App',
template: './src/templates/index.html'
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /\.js$/,
use: [
'angular-router-loader',
'babel-loader'
]
/* These 2 js loaders were failed attempts at solving this problem*/
}
]
}
};
ngApp.js
import * as angular from 'angular';
import ngRoute from'angular-route';
import './ngApp.controller.root.js';
const ngApp = angular.module('ngApp', [ngRoute]);
ngApp.config(function($routeProvider){
$routeProvider.when('/', {
controller: 'ngAppRootController',
templateUrl: './ngApp.view.root.html'
}).otherwise({
redirectTo: '/'
});
});
ngApp.$inject = [ngRoute];
webconsle error:
angular.js:138 Uncaught Error: [$injector:modulerr] Failed to instantiate module ngApp due to:
Error: [$injector:unpr] Unknown provider: t
If you see error like 'Unknown provider' with random letter like 'e'/'t'/'x', means you need ngInject plugin to let Webpack know which dependency to inject.
Add 'ngInject' right on next line after any dependency injection in Angular file:
ngApp.config(function($routeProvider, serviceWhateverYouRequire) {
'ngInject'
$routeProvider.when('/', { bla-bla-bla
or
ngApp.config(['$routeProvider', 'serviceWhateverYouRequire', function($routeProvider, serviceWhateverYouRequire) {
$routeProvider.when('/', { bla-bla-bla
We use these libraries for devDependencies with webpack#4.12.0
"ng-annotate-loader": "0.1.0",
"ng-annotate-webpack-plugin": "^0.3.0",
"ts-ng-annotate-loader": "^0.2.1"

jQuery requires a window with a document in webpack

I'm using ReactJS.net (server-side render) and when I use jquery in Webpack then I got error
here is my error
Error while rendering "Components.ToDoListSkeleton" to
"react_0LmYYfSk30qdrKJQe4McUQ": Error: jQuery requires a window with a
document
at module.exports (Script Document [5]:51:87) -> module.exports=global.document?factory(global,true):function(w){if(!w.document){throw
new Error("jQuery requires a window with a document");}return
factory(w);};}else {factory(global);} // Pass this if window is not
defined yet
at new ToDoListSkeleton (Script Document [5]:26:903)
at ReactCompositeComponentMixin._constructComponentWithoutOwner (Script Document [2]:8271:28)
at ReactCompositeComponentMixin._constructComponent (Script Document [2]:8253:22)
at ReactCompositeComponentMixin.mountComponent (Script Document [2]:8172:22)
at ReactReconciler.mountComponent (Script Document [2]:1977:36)
at Script Document [2]:19549:37
at Mixin.perform (Script Document [2]:3788:21)
at renderToStringImpl (Script Document [2]:19544:25)
at renderToString (Script Document [2]:19574:11)
at Script Document [7] [temp]:1:16 Line: 19549 Column:37
here is my webpack config
"use strict";
var path = require('path');
var WebpackNotifierPlugin = require('webpack-notifier');
var webpack = require("webpack");
module.exports = {
context: path.join(__dirname, 'Content'),
entry: {
server: './server'
},
output: {
path: path.join(__dirname, 'build'),
filename: '[name].bundle.js'
},
module: {
loaders: [
// Transform JSX in .jsx files
{ test: /\.jsx$/, loader: 'jsx-loader?harmony' },
{ test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" }
]
},
resolve: {
// Allow require('./blah') to require blah.jsx
extensions: ['', '.js', '.jsx']
},
externals: {
//// Use external version of React (from CDN for client-side, or
//// bundled with ReactJS.NET for server-side)
react: "React"
},
plugins: [
new WebpackNotifierPlugin(),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
})
]
};
Any help or suggestions would be appreciated, Thanks.
jQuery is only designed for use in a browser, and does not support server-side rendering. You'll need to remove jQuery from any of your code that you want to use server-side.

Load libraries from an external lib folder without npm in webpack

I am getting started to migrate my angular app to webpack. I have a file structure as belows:
- app/
------ app.js
------ index.html
- lib/
----- angular.js
----- jquery.js
----- ...
- webpack.config.js
Due to restrictions, I cannot use npm to install libraries. All my library files are located in lib and other folders. My webpack config looks like below:
var webpack = require('webpack'),
path = require('path');
module.exports = {
context: __dirname,
entry: {
app: [ './app/app.js'],
vendors: ['angular']
},
output: {
path: __dirname + '/build',
filename: 'bundle.js'
},
resolve: {
alias: {
angular: __dirname + "/lib/angular"
}
},
debug: false,
devtool: 'source-map',
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
},
{
test: /\.css$/,
loader: "style-loader!css-loader"},
{
test: /\.png$/,
loader: "url-loader?limit=100000"},
{
test: /\.jpg$/,
loader: "file-loader"
},
{
test: /\.json/,
loader: 'json'
}
]
},
plugins: [
new webpack.ProvidePlugin({
angular: "angular"
}),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js', Infinity)
]
}
I get the error
angular.js?848f:80Uncaught Error: [$injector:modulerr] Failed to instantiate module myApp due to:
Error: [$injector:nomod] Module 'myApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
app.js looks like below
angular.module("myApp", [])
.controller("myCtrl", function(){ ... });
Thanks for the help!
First, fix typo vendor instead of vendors in your entries. It should match name in CommonsChunkPlugin
entry: {
app: [ './app/app.js'],
vendor: ['angular']
},
Second, remove ProvidePlugin
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js', Infinity)
]
Now it should works.
But i don't know if it's correct way to load external libs with webpack, actually. (Webpack is super black box for me, gulp is much more predictable). So now it works, but without proper DI.

React webpack create bundle with separated react

is possible to configure webpack to not compile react inside bundle file? I would like to have more react applications in one page and I would like to load react library only once to get smallest size. How to achieve this?
In same situation I created final bundle with all small "applications" + React bundled once.
// components/index.js (webpacks entry point)
require("expose?React!react");
require("expose?MarketProductListing!./MarketProductListing");
require("expose?ProductDetail!./ProductDetail");
require("expose?MarketSearch!./MarketSearch");
Then, I include bundled JS via <script/> tag.
<script src="js/components.bundle.js"></script>
Now, I can access React, MarketProductListing, ... components in JS and render them where needed.
As you see, I use expose-loader for Webpack.
Webpack config
var path = require('path');
var webpack = require('webpack');
const js_dir = path.join(__dirname, 'src');
module.exports = {
devtool: 'eval',
entry: {
components: path.join(js_dir, 'components'),
},
output: {
path: js_dir,
filename: '[name].bundle.js'
},
plugins: [
new webpack.ProvidePlugin({
'es6-promise': 'es6-promise',
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
})
],
module: {
loaders: [
{ test: /\.js$/, loaders: ['babel'] }
]
},
resolve: {
extensions: ['', '.js', '.json']
}
};

Why webpack bundled as 'System.register'

I am trying develop a angular2 app using webpack, but it end up with an error in browser console say: Uncaught ReferenceError: System is not defined.
When I looked into the bundled js, I saw it is using System.register like below:
function(module, exports) {
System.register(['angular2/platform/browser', './app.component'], function(exports_1) {
var browser_1, app_component_1;
return {
setters:[
function (browser_1_1) {
browser_1 = browser_1_1;
},
function (app_component_1_1) {
app_component_1 = app_component_1_1;
}],
execute: function() {
browser_1.bootstrap(app_component_1.AppComponent);
}
}
});
// ...
My webpack.config.js is pretty simple as below:
var webpack = require('webpack');
module.exports = {
context: __dirname,
entry: "./app/boot.ts",
devtool: 'inline-sourcemap',
output: {
path: __dirname + "/dist",
filename: "bundle.js"
},
module: {
loaders: [
{test: /\.ts$/, loader: 'ts-loader'}
]
}
};
Can anyone fix for me? thanks.
As suggested by #Ron
If you're using Webpack to bundle your application you must transpile your code to commonjs. The solution is to change module to commonjs in your tsconfig.json.
// tsconfig.json
"module" : "commonjs"
Here's a list of seed repositories for angular2 using webpack that can be helpful
ng2-webpack-play by #pkozlowski-opensource
angular2-webpack-starter by #gdi2290
ng2-webpack by #ocombe
As an extra, I recommend you to watch Modularity and Packaging for Angular2 Applications by Pawel from AngularConnect2015

Resources