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

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"

Related

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.

webpack with angular 1 and bower

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.

How to use templates with angular 1.x and webpack

Im trying to use webpack with my angular app but whenever I try loading in the html to the template I get errors. This is the one I'm currently getting:
Module parse failed: C:\Users\Fabian\Dropbox\FixMyCity\FixMyCity\src\FixMyCity.Web\App\settings\settings.html Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
Which makes me think that I don't have the right loader for html, but i've tried it with both raw-loader and html-load and neither of them have worked for me.
Here is my current webpack.config.js
module.exports = {
entry: './App/app.js',
output: {
filename: './wwwroot/app-bundle.js'
},
loaders: [
{ test: /\.html$/, loader: 'html' },
{ test: /\.css$/, loader: 'style!css' },
]
};
app.js
var app = angular.module('app', ['auth0', 'angular-storage', 'angular-jwt', 'ngRoute'])
.config(['$routeProvider', 'authProvider', 'jwtInterceptorProvider', '$httpProvider', configFunction])
function configFunction($routeProvider, authProvider, jwtInterceptorProvider, $httpProvider) {
// Configure routes for your application
$routeProvider
.when('/', {
controller: 'HomeCtrl',
template: require('./home/home.html'),
requiresLogin: true
})
}
You must install html-loader from npm, after that you have to put in property loader the value 'html-loader'.
Like this:
module.exports = {
entry: './App/app.js',
output: {
filename: './wwwroot/app-bundle.js'
},
loaders: [
{ test: /\.html$/, loader: 'html-loader' },
{ test: /\.css$/, loader: 'style!css' },
]};

The following modules couldn't be hot updated: (Full reload needed)

I'm trying to setup hot module reloading in a react/typescript (with TSX) environment. I have used the react/redux real-world example as a model in getting things going, and this is what I have so far:
server.js
var webpack = require('webpack')
var webpackDevMiddleware = require('webpack-dev-middleware')
var webpackHotMiddleware = require('webpack-hot-middleware')
var config = require('./webpack.config')
var app = new (require('express'))()
var port = 3000
var compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
app.use(webpackHotMiddleware(compiler))
app.use(function(req, res) {
res.sendFile(__dirname + '/index.html')
})
app.listen(port, function(error) {
if (error) {
console.error(error)
} else {
console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
}
})
webpack.config.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
path.resolve('./src/index.tsx'),
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({ template: './index.html' })
],
module: {
loaders: [
{ test: /\.tsx?$/, loader: 'ts-loader' }
]
},
resolve: {
extensions: ['', '.ts', '.tsx', '.js', '.json']
},
}
index.tsx
import * as React from 'react';
import { render } from 'react-dom';
import Root from './containers/root';
render(
<Root />,
document.getElementById('root')
);
containers/root.tsx
import * as React from 'react';
export default class Root extends React.Component<void, void> {
render(): JSX.Element {
return (
<p>boom pow</p>
);
}
}
Changing <p>boom pow</p> to <p>boom boom pow</p> in the root element kicks off this in the javascript console in the browser:
[HMR] bundle rebuilding
client.js?3ac5:126 [HMR] bundle rebuilt in 557ms
process-update.js?e13e:27 [HMR] Checking for updates on the server...
process-update.js?e13e:81 [HMR] The following modules couldn't be hot updated: (Full reload needed)
This is usually because the modules which have changed (and their parents) do not know how to hot reload themselves. See http://webpack.github.io/docs/hot-module-replacement-with-webpack.html for more details.
process-update.js?e13e:89 [HMR] - ./src/containers/root.tsx
process-update.js?e13e:89 [HMR] - ./src/index.tsx
I've stepped through these steps as best I can tell, but am still having no luck.
What am I missing?
The problem, as mentioned by commenters, was missing in my loader - I'm not sure if this had anything to do with it, but I also switched to using babel after typescript - and having typescript compile to ES6. New config below:
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
path.resolve('./src/index.ts'),
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({ template: path.resolve('./src/index.html') })
],
module: {
loaders: [
{ test: /\.tsx?$/,
loaders: [
'react-hot',
'babel?presets[]=es2015',
'ts-loader'
]
},
{ test: /\.json$/,
loader: 'json'
}
]
},
resolve: {
extensions: ['', '.ts', '.tsx', '.js', '.json']
},
}
if someone still struggles with this see the readme: https://github.com/webpack-contrib/webpack-hot-middleware/blob/master/README.md
This module is only concerned with the mechanisms to connect a browser client to a webpack server & receive updates. It will subscribe to changes from the server and execute those changes using webpack's HMR API. Actually making your application capable of using hot reloading to make seamless changes is out of scope, and usually handled by another library.
webpack-hot-middleware doesn't handle hot reload, you'd need to use react-hot-loader for example

_angular.angular undefined error when loading angular app built by webpack

I am trying to bootstrap an AngularJS app built with Webpack. But I get the following error and the module isn't set up.
TypeError: _angular.angular is undefined
I dig into the generated code chunk and find that the _angular.angular is from
var _angular = __webpack_require__(1);
var _angularUiBootstrap = __webpack_require__(3);
_angular.angular.module('app', [_angularUiBootstrap.bootstrap]).constant('_', window._).run(function ($rootScope) {
$rootScope._ = window._;
It looks like that _angular.angular.module should be _angular.module. I probably use a wrong way to bootstrap angular, or use an incorrect Webpack configuration. Here is my code:
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var srcDir = 'static_src';
var outputDir = 'static';
module.exports = {
devtool: 'source-map',
debug: true,
entry: {
app: path.resolve(srcDir, 'app.js')
},
output: {
path: outputDir,
filename: '[name].bundle.js',
sourceMapFilename: '[name].map',
chunkFilename: '[id].chunk.js'
},
resolve: {
extensions: ['', '.js', '.less', '.css'],
alias: {
npm: __dirname + '/node_modules'
}
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
query: {
presets: ['es2015'],
plugins: ['syntax-decorators', 'ng-annotate']
},
exclude: /node_module/
},
{ test: /\.less$/, loader: 'to-string!css!less' },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
{ test: /\.(png|gif|jpg)$/, loader: 'file?name=images/[name].[ext]' }
]
},
plugins: [
new webpack.NoErrorsPlugin(),
new webpack.optimize.DedupePlugin(),
new ExtractTextPlugin('[name].css')
]
};
app.js
import { angular } from 'angular';
import { bootstrap } from 'angular-ui-bootstrap';
angular.module('app', [bootstrap]);
I am using angular 1.5.0 and webpack 1.12.14.
Thanks in advance.
your error is in the require statement. you are using
import { angular } from 'angular';
this implies that there is an angular variable inside of the exported angular module.
what you want to use is
import angular from 'angular';
try that.

Resources