how to get webpack to bundle node_modules for angular 1 - angularjs

I am about to move angular 1 + typescript project build setup from gulp to webpack, the only part I am stuck with is, how to bundle node_modules js file in proper sequence.
I was till now using bower for client side dependencies, and gulp has wiredep plugin which will look into bower dependencies section + main section to build the dependency order and get it to bundle it properly.
Now I understand that webpack philosophy is different, we should depend upload whatever is imported rather than any dependencies section as such.
so to get it to work I will need to do: move all dependencies from bower.json to package.json
currently as I am using typings, tsc considers the typings and gives me the output, I really don't need to write imports for bower packages as such.
So if i understand correctly, to get it work with webpack,
a) I should get away with typings and then directly import the js
files inside all my ts files??
As I understand, all the js modules from npm do work with modules, so does webpack really needs typings files?
OR
b) I should write a separate vendor.ts, where I should maintain the
sequence of imports (for js and css) myself,
but then that would be little painful to do (given I am used to wiredep handling it for me).
But then this will allow me bundle the vendor files separately using chunks-plugin
OR
c) is there any other standard way to handle this.
This is kinda pain point to move angular 1 from gulp to webpack.

When you import a module from a TypeScript file that's going to be loaded by webpack, it'll get it's content from node_modules and bundle it into the output file.
index.ts
import * as angular from "angular";
const myApp = angular.module("myApp", []);
myApp.controller("MyController", function PhoneListController($scope) {
$scope.phones = [
{
name: "Nexus S",
snippet: "Fast just got faster with Nexus S."
}, {
name: "Motorola XOOM™ with Wi-Fi",
snippet: "The Next, Next Generation tablet."
}, {
name: "MOTOROLA XOOM™",
snippet: "The Next, Next Generation tablet."
}
];
});
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
...
<script src="bundle.js"></script>
</head>
<body ng-controller="MyController">
<ul>
<li ng-repeat="phone in phones">
<span>{{phone.name}}</span>
<p>{{phone.snippet}}</p>
</li>
</ul>
</body>
</html>
webpack.config.js
module.exports = {
entry: "./index.ts",
output: {
filename: "./bundle.js"
},
devtool: "source-map",
resolve: {
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
loaders: [
{ test: /\.tsx?$/, loader: "ts-loader" }
],
preLoaders: [
{ test: /\.js$/, loader: "source-map-loader" }
]
}
};
Add angular, #types/angular, ts-loader, source-map-loader, typescript to your packages.json and run webpack.
It'll bundle everything inside a single file named bundle.js which will be used by your index.html.

Related

grunt-babel is not transpiling parent folder react jsx files

I am using grunt to transpiling react jsx files and it's perfectly works as expected by using grunt-babel along with presets: ["env", "react"],plugins: ["transform-es2015-modules-amd"]
The problem I have is,grunt-babel transpiling JSX files which are placed in a same directory but I need to transpile JSX files which are one level up to root folder directory.Below is the detail explanation:
Folder Structure :
ReactApp
- App // grunt-babel and relevant plug-ins, presets installed here
- config
- node_modules
- JSX // it's transpiling and working
- test.jsx
- JSX_generated
- test.js
- gruntfile
- package
- JSX // jsx file source and it's not transpiling
- test.jsx
- JSX_generated // transpiled jsx file output expected
- test.js
- App.js
- index.html
gruntfile :
module.exports = function (grunt) {
'use strict';
grunt.initConfig({
babel: {
options: {
sourceMap: false,
presets: ["env", "react"],
plugins: ["transform-es2015-modules-amd"]
},
dist: {
files: [{
expand: true,
cwd: './JSX',
src: ['*.jsx'],
dest: './JSX_generated',
ext: '.js'
}]
}
}
});
grunt.loadNpmTasks('grunt-babel');
grunt.registerTask('default', ['babel']);};
Above grunt config is woring fine for the jsx folder placed under App folder, the thing is I need to transpile the JSX folder which is placed out of App folder.
Changed grunt config cwd as cwd: './../JSX' , dest as dest: './../JSX_generated',
Getting the following error :
Running "babel:jsx" (babel) task
Warning: Unknown plugin "transform-es2015-modules-amd" specified in "base" at 0, attempted to resolve relative to "../JSX"
sample jsx file :
import React from 'react';
import AppData from './AppData';
import Loader from './Loader';
class Test extends React.Component {
render() {
return <p>hello </p>
}
}
ReactDOM.render(<Test />, document.getElementById('container'));
Is there a way to transpile files one level up from the grunt or node have been installed ?
For anyone having an issue like this, the solution is use
absolute paths
../Users/app/node_modules/babel-preset-es2015
or use require like below :
var babelenv = require('babel-preset-env');
var babelreact = require('babel-preset-react');
var babelamd = require('babel-plugin-transform-es2015-modules-amd');
and presets: [ babelenv, babelreact],plugins : [ babelamd ]

How to build unified $templateCache when migrating AngularJS 1.x project from gulp & bower to webpack 3

Have a large AngularJS 1.6 project (~120 JS files), which is currently built through gulp/bower.
Looking to migrate over to using yarn & webpack, and we would prefer not to have to modify our project files just to implement webpack. Each of our AngularJS component JS files are wrapped in a IIFE, so they are already out of the global scope.
One of our gulp steps uses the gulp-angular-templatecache module, which collects all of our HTML files and neatly compacts them into a single $tmplateCache loader module.
angular.module("ourApp").run(["$templateCache", function ($templateCache) {
$templateCache.put("/app/components/ourComponent1.html", "<div id=\"component1-html\"> ... </div>\r\n");
$templateCache.put("/app/components/ourComponent2.html", "<div id=\"component2-html\"> ... </div>\r\n");
// etc...
});
I have managed to figure out how to resolve most of our other build processes using webpack, but this one is giving me a problem.
I have looked at the ngtemplate-loader package, but do not think this would work for our needs because of the following:
Would require us to update all of our existing HTML templates to use 'require("./template.html")'
This would create a separate webpack module for each HTML template, which seems very inefficient.
Probably most important, I haven't been able to get it to work.
The current webpack configuration I have setup is based on a simple demo, and splits the project files out from the vendor files. Our project files are bundled up into a 'app.[hashcode].js' file into the /dist folder.
Ultimately, I would like to be able to inject the compiled $templateCache module, into a specific point in our final 'app.[hashcode].js' bundle file. However, right now I would be satisfied with the $templateCache definition file being created into a separate bundle file.
Is there an existing webpack plugin, or loader, or combination of plugin(s)/loader(s), that I could use to accomplish this build step? Is this even possible with webpack?
This is the base directory structure for the demo project:
/dashboard
/app
/assets
/global
global.less
app.less
/components
/controllers
dashboard.controller.js
/directives
yep-nope.directive.js
/messenger
messenger.directive.js
messenger.html
/services
github-status.service.js
dashbboard.config.js
dashboard.module.js
app.js
/dist
app.4f12bb49f144e559bd9b.js
assets.css
index.html
vendor.b0a30c79aa77e0126a5c.js
index.html
package.json
webpack.config.js
This is the current working webpack.config.js file:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
context: __dirname,
entry: {
app: path.resolve(__dirname, 'app/app.js'),
vendor: ['angular','angular-sanitize']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'less-loader']
})
},
{
test: /\.js$/,
loader: 'ng-annotate-loader'
},
{
test: /\.html$/,
exclude: path.resolve(__dirname, 'app/index.html'),
use: [
{ loader: 'html-loader', options: { minimize: false } }
]
}]
},
plugins: [
new CleanWebpackPlugin(['dist','assets/**/*.css']),
new HtmlWebpackPlugin({
title: 'GitUp',
template: 'index.html',
inject: 'body'
}),
new webpack.optimize.CommonsChunkPlugin({
name:"vendor", filename:"[name].[chunkhash].js"
}),
new ExtractTextPlugin('assets.css')
]
};
This is the webpack 'entry' file app/app.js:
require('./assets/app.less');
require('../node_modules/angular/angular.js');
require('../node_modules/angular-sanitize/angular-sanitize.js');
require('./components/dashboard.module.js'); // Define module
require('./components/dashboard.config.js'); // Setup config
// Load in all components files, except for files already loaded above
var reqCtx = require.context('./components', true, /^(?!.*(?:dashboard\.config|dashboard\.module)).*\.js$/);
reqCtx.keys().forEach(reqCtx);
If needed, I can provide the entire sample project...
This may or may not be the answer you're looking for but in the past I've used html-loader to allow me to require my component template URLs, and it worked brilliantly:
https://www.npmjs.com/package/html-loader
It just inlines the template in your bundled script.

How to migrate from imports using <script> to module bundler?

I have a project which uses Angular. It does not use a task manager nor dependency manager and all libs are stored in repo and included using plain old <script> tag like <script src="libs/angular/angular.min.js"></script>.
I want to modernize the application by introducing a module bundler and automating the build process. The original idea was gulp + bower, but I see that webpack + npm3 are a trend now.
There is no issue with gulp + bower because of things like gulp-inject, but I can’t find anything similar which works with webpack.
Are there any tools which would allow me to use the existing code as it is and write only new modules using webpack?
Here's the solution i've got so far. Since the webpack requires a single entry point per bundle, i still have to import all those legacy js in a single file. So i decided to use ES6 import (or webpack's require) in that entrypoint called index.js
here's the how webpack config looks like
var webpack = require('webpack');
var path = require('path');
var basePath = __dirname + "/target/app";
module.exports = {
context: basePath,
entry: {
app: './index.js',
vendor: './vendor.js'
},
output: {
path: basePath + "/build",
filename: '[name].js'
},
module: {
loaders: [
{test: /\.js$/, loader: 'babel?presets=es2015', exclude: /node_modules/},
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
}),
new webpack.ProvidePlugin({
"$": "jquery",
"jQuery": "jquery",
"window.jQuery": "jquery",
"_": "lodash"
}),
],
};
and so in index.js i did following
import './app/component1.js'
import './app/component2.js'
//all the rest imports from index.html
as for the third part libraries like jquery, angular, etc... i decided to describe that imports in separate bundle and so there's another bundle called vendor.js
import './libs/lodash.js'
import './libs/jquery.js'
//and all the rest libraries
//note that here we can use now libs from npm node_modules like
import 'angular' //will take angular from node_modules/angular
Important thing which i faced while doing this, is that legacy modules are not really compatible with webpack because of using global variables like $, _, etc... ProvidePlugin helps here and add require({module}) to the modules where the provided {variable} met as it's described in config 'variable': 'module'
Note that i used CommonsChunkPlugin to avoid having dependent modules in both bundlers, like angular is required in index.js and vendor.js but with this plugin webpack will handle that and add js code only in vendor.js

Can't set up React/Babel/Webpack

So I was trying to set up the React/Babel/Webpack environment but I had some trouble doing so. I started creating a new folder, did the npm init and then I followed everything in this tutorial: https://facebook.github.io/react/docs/package-management.html
First, I've installed webpack globally
I've created a index.js with the same content on the tutorial
I've created a .babelrc file with { "presets": ["react"] }
Ran the npm install --save react react-dom babel-preset-react babel-loader babel-core
Then, when I run the command webpack main.js bundle.js --module-bind 'js=babel-loader' it gives me an error: "Module parse failed ~ You may need an appropriate loader to handle this file type.
Any idea guys? I've literally copy and pasted every step from the tutorial and I am sure all the files are correct. Thanks in advice!
Create file webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './main.js',
output: { path: __dirname, filename: 'bundle.js' },
module: {
loaders: [{
test: /.js?$/,
loader: 'babel-loader',
exclude: /node_modules/
}]
},
};
Run
webpack
and it will generate bundle.js for you.
Now make sure you have added index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
</head>
<body>
<div id="example"></div>
<script src="bundle.js"></script>
</body>
</html>
Looks like you accessing webpack from global. You might have installed webpack by doing
npm install -g webpack
Now,
Install webpack locally,
npm install webpack
and run.
./node_modules/webpack/bin/webpack.js main.js bundle.js --module-bind 'js=babel-loader'

Bootstrap.css not getting added to index.html in dist

I have a grunt task configured (I am working existing project). I am not sure where to find particular task. I have an "index.html" file getting created and added to the "dist" folder after every compile and build. But in the index.html i manually have to add the following every time:
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.css">
and also the -
<base href="/">
For AJS.
What might be the possible issue?
I don't want to edit bower.json instead do it using grunt task. so how do i do it?
I have the following:
var buildConfig = module.exports = {
// Wiredep options
wiredepOptions: {
//
// devDependencies: true, // <-- injects bower devDependencies
//
// exclude: [ // <-- List of patterns to exclude
//
// /bootstrap\.js/
// ]
"overrides": {
"bootstrap": {
"main": [
"dist/css/bootstrap.css"
]
}
},
This gives me error. how do i resolve it?
This is because the main object in Bootstrap's bower.json mention a reference to the less file not the css
"main": [
"less/bootstrap.less",
"dist/js/bootstrap.js"
],
Wiredep is the grunt task that is responsible for injecting those assets so it have no idea where the CSS file is. You can do it by providing an override in wiredep task in your gruntfile.js as follow:
wiredep: {
...,
overrides: {
'bootstrap': {
'main': [
'dist/js/bootstrap.js',
'dist/css/bootstrap.css' // Note this
]
}
}
}
},
Running grunt wiredep again will inject the CSS file to your HTML as expected.
Note: This won't work unless your HTML have this HTML comment
<!-- bower:css -->
The styles will be injected here
<!-- endbower -->
I could not resolve it with editing Gruntfile but added this in bower.json :
"overrides": {
"bootstrap": {
"main": [
"dist/css/bootstrap.css"
]
}

Resources