webpack.ProvidePlugin angular - angularjs

I am trying to use angular NG6 starter. in its source code, import angular from angular is written almost every js file. So I try this:
new webpack.ProvidePlugin({
// $: "jquery",
// jQuery: "jquery",
// "window.jQuery": "jquery",
'angular': 'angular',
}),
But it can not work. I dont know why, and how to solve this issue.

Here the solution to the first error message in your screenshot "angular.module is not a function": Angular 1 is not working nicely with webpack without a shim (see https://github.com/webpack/webpack/issues/2049). Try this webpack loader config:
module: {
loaders: [
/*
* Necessary to be able to use angular 1 with webpack as explained in https://github.com/webpack/webpack/issues/2049
*/
{
test: require.resolve('angular'),
loader: 'exports?window.angular'
},
]
},
plugins: [
new webpack.ProvidePlugin({
'angular': 'angular',
}),
],
This should initialize the angular object properly instead of the default action of setting it to an empty object (which does not have a property named module).

U need to use sth like this:
var app = angular.module('RequiredName', ['ui.router','ui.bootstrap']);
and use this on app file and call your app module like in the parts of project that u are going to use any function or method implemented in your app.js file in app.factory or app.controller or...

Related

Correct way to load AngularJS templates for Webpack 4?

So far I've been able to bundle up all our controllers/directives/services into 1 script and I also bundled all the vendor scripts into another script file. Now I'm having trouble figuring out what the right way to load the AngularJS template files are. We are currently using Grunt and just copying the exact folder structure over to the dist folder but clearly this won't work in Webpack. Here is an example of our project structure(from the John Papa style guide)
My project inside the dist folder is currently rendered as follows:
Anybody have any input?
AngularJS templates are html files, so you need to add some loader for handling them.
You have multiple options, bundle those html files into the js bundle, using html-loader, pros of this approach is that your app won't make ajax call for the template, cons, your js bundle size will become large.
This will allow you to "require" your html template inside your controllers.
copy those raw files using copy-webpack-plugin, this way it will work the same way it works with Grunt (providing templateUrl path to the file that was copied).
In-order to be specific regarding lazy-loaded files you can attach .lazy.html suffix.
Then, enable file-loader on the .lazy.html files & assign it to templateUrl, and the regular once use with template: require('template.html').
As of best practice, I would "require" critical templates so they will be in the js bundle, and lazy load (via templateUrl) non-critical ones.
This is an example of webpack.config.js file:
module.exports = {
module: {
rules: [
{
test: /\.lazy\.html$/,
use: [
{
loader: 'file-loader',
options: {},
},
],
},
{
test: /\.html$/,
exclude: /\.lazy\.html$/
use: [
{
loader: 'html-loader',
options: {
minimize: true,
},
},
],
},
],
},
};
// critical.component.js
angular.
module('myApp').
component('greetUser', {
template: require('critical.html'),
controller: function GreetUserController() {
this.user = 'world';
}
});
// none-critical.component.js
angular.
module('myApp').
component('greetUser', {
templateUrl: require('non-critical.lazy.html'),
controller: function GreetUserController() {
this.user = 'world';
}
});

Do web pack import lib source into every single module?

I started a FE app with react-create-app. later, I moved the exact same source code to a django project of mine with a custom webpack configuration (so it can be loaded with django's static files).
Long story short, my custom webpack build is almost twice as big as the react-create-app build. 278kb vs 478kb
Most of the modules are importing jquery and bootstrap js. So my guess is that my configuration is importing said libraries into each module.
Most of my modules import look like :
let React = require('react');
import $ from 'jquery/src/jquery';
import 'bootstrap/dist/js/bootstrap';
And my webpack config looks like
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry:[
'./app.jsx'
],
output:{
filename:'../app.bundle.js'
},
module:{
loaders:[
{
test:/\.js[x]?$/,
loader:'babel-loader',
exclude:/(node_modules)/,
query:{
presets:['es2015','react']
}
}
]
},
plugins: [
new UglifyJsPlugin()
]
};
Granted is a very basic webpack config. Hence, my guess is that I'm missing a existing plugin in react-create-app, that avoids to import the same library over and over. I have look for information in the docs to wether Webpack would do this, but can't seem to find any.
I've look into commons chunks, but that seems to solve other problem, and I don't really need or want to have an independent chunks bundle.
After further research I changed my webpack config file to :
plugins: [
new UglifyJsPlugin(),
//enable production build:
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
//expose jquery window.$ global
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
tether: 'tether',
Tether: 'tether',
'window.Tether': 'tether',
})
]
So bootstrap.js is able to find the $ object in window, instead of importing the whole source library into the module as before.
I also changed:
import $ from 'jquery/src/jquery';
to
let $ = require('jquery');
It reduced the filsize from 480kb to 300 kbs, which seems in line with the react-create-app bundle.

Using a text loader in Webpack for RequireJS text plugin

So my AngularJS code looks like this:
define(['angular', 'text!./template.html'], function (angular, template) {
'use strict';
return angular.module('app.widget', [])
.directive('MyWidget', function(){
//.... use the template here
})
I'm using the text plugin for RequireJS to get the html template and use in in the AngularJS directive.
I want to use webpack and it's reading the AMD style code ok but it can't work with the text plugin.
Does anyone know how to get the text-loader for webpack to work with requirejs?
There are some solutions out there and a discussion thread but I can't get them to work.
In my webpack.config.js I've got
loaders: [
{ test: /^text\!/, loader: "text" }
]
Thanks
Actually you need dont need to specify node modules path. It works if you specify just the name of the actual loader like below
resolveLoader: {
alias: { "text": "text-loader" }
},
You need to install raw-loader, which is the webpack equivalent for loading raw files
npm i raw-loader
Then you need to alias the requireJS style with the raw-loader (resolveLoader is to be put in the root of the webpack config object)
resolveLoader: {
alias: {
'text': {
test: /\.html$/,
loader: "raw-loader"
},
}
}
Check this SO question: Webpack loader aliases?
A similar solution which worked for me with Webpack 2.2:
resolveLoader: {
alias: {
// Support for require('text!file.json').
'text': 'full/path/to/node_modules/text-loader'
}
}
And install text-loader:
npm install text-loader

requirejs + backbonejs + optimizer = backbone undefined

Backbone doesn't get called in the indexview module.
using requirejs 2.1.5/2.1.4 and backbonejs 0.9.10
main.js after running r.js
...
// this is causing the backbone to return
// null/undefined in the next define call below
define("backbone", function(){});
define('views/index/IndexView', [
'underscore',
'backbone',
'text!templates/index/indexTemplate.html'
], function(_, Backbone, indexTemplate){
console.log(Backbone); // returns undefined
var IndexView = Backbone.View.extend({
...
BUT if I take out the first define call that registers backbone as a module, everything
works fine. but backbone-min.js gets loaded separately. but for now it's the only way
to make the script run. I am definitely missing something here.
main.js
require.config({
paths: {
underscore : 'libs/underscore/underscore-min',
backbone : 'libs/backbone/backbone-min'
templates : '../templates'
},
shim: {
'backbone': {
deps: ['jquery','underscore'],
exports: 'Backbone'
}
}
});
require(['app'], function(App){
App.initialize();
});
build.js
({
appDir: "../",
baseUrl: "js",
dir: "../../build",
optimize: "none",
paths: {
"jquery": "libs/requirejs/require-jquery",
"underscore" : 'libs/underscore/underscore-min',
"backbone": 'libs/backbone/backbone-min',
"templates": '../templates',
},
modules: [
{
name: "main",
exclude: ["jquery"]
}
]
})
I'm still getting my feet wet with backbone and requirejs.
any feedback is much appreciated.
First of all, you don't need that define('backbone',...). What is that part for anyways? You don't need to define Backbone as a module. Requirejs is doing the job of making Backbone available for you to use throughout your framework. As you can see in your code, by calling Backbone.View.extend(), Backbone already exists. If you want to inspect it, don't use console.log, use console.dir instead. In the chrome inspector it formats the output nicely.
Secondly, add underscore to the backbone deps array in your shim.
I've just had this issue, you need to add the 'shim' from your main.js to your build.js file, and will work like a charm ;)

Loading Dynamic Require.js modules

Have spent the whole day on this and i think its time for a shout out. I am using require.js to include modules in my backbone app. This is what i have:
My requirejs config:
paths:
jquery: "backbone/initializers/jquery_loader"
jqueryui: "backbone/initializers/jqueryui_loader"
modules:
- name: 'application'
- name: 'jquery'
exclude: ['application']
- name: 'jqueryui'
exclude: ['application', 'jquery']
- name: 'email'
exclude: ['application']
- name: 'department_home'
exclude: ['application']
priority: ['application', 'jquery', 'jqueryui']
My jquery_loader:
define ["jquery.min"], () ->
jQuery = $
jQuery.noConflict(true)
My jqueryui_loader:
define ['jquery.ui.all'], () ->
My email module:
define ['marionette', 'jqueryui', 'tags'], (Marionette, ui, tags) ->
My department home module
define ['marionette', 'jqueryui', 'dept_tags'], (Marionette, ui, tags) ->
Everything works as expected and compiles, but maybe i don't understand it or i am missing something, the email module is loaded dynamically on a click event, and it has jqueryui included in it, which i believe is just an r.js optimized file.
Now i do another click event after email module is loaded, and i see that the department module also has jquerui in it, both come in at 90KB, what i expected is for department module to use the jqueryui thats already loaded by the email module.
Appreciate your help!
I think you shouldn't use jquery loader like this. You should use the shim property to initialize the noConflict. I've answered something similar a few days ago.
In your case it would be something like this (but in coffeescript then):
require.config({
paths: {
jquery: "path/to/jquery",
jqueryui: "path/to/jqueryui"
},
shim: {
jquery: {
exports: 'jQuery',
init: function() {
return this.jQuery.noConflict();
},
jqueryui: {
deps: ['jquery']
}
}
});

Resources