Deploying Angular 2 tutorial webpack build - angularjs

I am currently trying to learn ng2.
I have followed the tutorial here : https://angular.io/docs/ts/latest/guide/webpack.html
And have found creating a dist of my build, upon attempting to run it, both locally and on Github Pages, I am receiving a 404 error on my bundle files.
I have followed the tutorial line for line and it does not appear to be working.
Can anyone help?
My webpack build is as follows :
webpack.common.js
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
module.exports = {
entry: {
'polyfills': './src/polyfills.ts',
'vendor': './src/vendor.ts',
'app': './src/main.ts'
},
resolve: {
extensions: ['', '.js', '.ts']
},
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw'
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
};
webpack.prod.js
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
module.exports = webpackMerge(commonConfig, {
devtool: 'source-map',
output: {
path: helpers.root('dist'),
publicPath: '/',
filename: '[name].[hash].js',
chunkFilename: '[id].[hash].chunk.js'
},
htmlLoader: {
minimize: false // workaround for ng2
},
plugins: [
new webpack.NoErrorsPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618
mangle: {
keep_fnames: true
}
}),
new ExtractTextPlugin('[name].[hash].css'),
new webpack.DefinePlugin({
'process.env': {
'ENV': JSON.stringify(ENV)
}
})
]
});
Index.html
<!DOCTYPE html>
<html>
<head>
<base href=/>
<title>Angular With Webpack</title>
<meta charset=UTF-8>
<meta name=viewport content="width=device-width,initial-scale=1">
<link href="/app.f053dbe7ce9dd32c3e43.css" rel="stylesheet">
</head>
<body>
<my-app>Loading...</my-app>
<script type="text/javascript" src="/polyfills.f053dbe7ce9dd32c3e43.js"></script>
<script type="text/javascript" src="/vendor.f053dbe7ce9dd32c3e43.js"></script>
<script type="text/javascript" src="/app.f053dbe7ce9dd32c3e43.js"></script>
</body>
</html>

I had the same problem! Do you have karma.conf.js in config dir? Your project structure should be like :

Related

React production build shows blank page

I have this problem where my react production build shows a blank page when served with simple node server. I have tried to tackle this problem different ways but cant find a solution to this. Any suggestions how to fix this problem would be much appreciated.
I am using BrowserRouter as the routing option on client side.
Here is my webpack.common.js code for the production build:
const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const outputPath = path.join(__dirname, "dist");
const port = process.env.PORT || 8000;
module.exports = {
context: __dirname,
entry: {
main: ["#babel/polyfill", "./src/App.js"]
},
output: {
path: path.join(__dirname, "dist"),
filename: "bundle.js"
},
resolve: {
modules: ["node_modules", "./src"],
extensions: [".js", ".jsx"]
},
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
use: "css-loader!sass-loader"
})
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: "css-loader"
})
},
{
test: /\.(js|jsx)$/,
loader: "babel-loader",
exclude: /node_modules/
},
{
test: /\.(jpg|jpeg|png|gif|mp3|svg)$/,
loaders: ["file-loader"]
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
}
]
},
plugins: [
new ExtractTextPlugin("bundle.css"),
new HtmlWebpackPlugin({
baseUrl: process.env.NODE_ENV == 'development' ? '/' : '/',
filename: "index.html",
template: path.join(__dirname, "./public/index.html")
})
],
devServer: {
port,
historyApiFallback: true,
publicPath: "/"
}
};
Here is the entry for the compiler to run the production build:
const webpack = require('webpack');
const merge = require('webpack-merge');
const webpackCommonConfig = require('./webpack.config.common');
module.exports = merge(webpackCommonConfig, {
plugins: [
new webpack.EnvironmentPlugin({ NODE_ENV: 'production' }),
],
devtool: "source-map",
devServer: {
compress: true,
},
});
Here is the code for node server serving the application:
const express = require('express')
const path = require('path')
const port = process.env.PORT || 8000
const fs = require('fs');
const app = express()
app.get(['/bundle.css', '/bundle.css.map'], (req, res) => {
res.writeHead(200, {'Content-Type': 'text/css'});
fs.createReadStream(path.resolve(__dirname, `../dist/${req.url}`)).pipe(res);
})
app.get(['/bundle.js', '/bundle.js.map'], (req, res) => {
res.writeHead(200, {'Content-Type': 'text/javascript'});
fs.createReadStream(path.resolve(__dirname, `../dist/${req.url}`)).pipe(res);
})
app.get('*', function (request, response){
response.sendFile(path.resolve(__dirname, '../dist', 'index.html'))
})
app.listen(port)
console.log("server started on port " + port)
Here is the index.html that is compiled to dist folder:
<!DOCTYPE html>
<html lang="en" style="height:100%">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.gif">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<title>Zoi</title>
<link href="bundle.css" rel="stylesheet"></head>
<body style="height:100%">
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<script type="text/javascript" src="bundle.js"></script></body>
</html>

after splitting Chunks in webpack unable to run app

in my react app i'm using webpack 4,before implementing split chunk everything is working fine but after splitChunks it generating vendor.js file and it showing on html file also but page is blank.
my webpack file
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CompressionPlugin = require('compression-webpack-plugin');
const VENDOR_LIBS =[
'antd','axios','moment','rc-time-picker','react',
'react-dom','react-ga','react-google-maps','react-loadable',
'react-redux','react-router','react-router-dom','recompose','redux','redux-thunk'
];
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
entry:{
vendor: VENDOR_LIBS,
main: './src/app.js',
},
output: {
path: path.join(__dirname, 'public'),
filename: '[name].chunkhash.bundle.js',
chunkFilename: '[name].chunkhash.bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.s?css$/,
use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
},{
test: /\.(gif|svg|jpg|png|ttf|eot|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader: "file-loader",
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'style.[contenthash].css',
}),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
}),
new WebpackMd5Hash(),
new CompressionPlugin({
algorithm: 'gzip',
test : /\.js$|\.css$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/,
threshold: 10240,
minRatio: 0.8
}),
],
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
name: 'vendor',
test: 'vendor',
enforce: true
},
}
},
runtimeChunk: true,
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({})
],
},
};
and in my /src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
<link rel="stylesheet" href="<%=htmlWebpackPlugin.files.chunks.main.css %>">
<title>Book Ambulance - Stanplus</title>
</head>
<body>
<div id="app">
</div>
<script src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>
<script src="<%= htmlWebpackPlugin.files.chunks.vendor.entry %>"></script>
</body>
</html>
you can that those files are loading in browser but page is blank
i have to questions
a) why my app not showing nothing even not any error(may be something in output,splitChunks or in html page).
b) after doing UglifyJsPlugin,CompressionPlugin and dynamically adding routes and import libs/files but also my vendor.js file size is 580 KB,except all these techniques how can i reduce the size of my vendor.js file

webpack-dev-server: Cannot get /

Unable to get a simple hello world working!
server.js
var webpack = require('webpack')
var WebpackDevServer = require('webpack-dev-server')
var config = require('./webpack.config')
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
inline: true,
historyApiFallback: true
}).listen(3000, '0.0.0.0', function (err, result) {
if (err) {
console.log(err)
}
console.log('Listening at 0.0.0.0:3000')
})
webpack.config.js
var path = require("path")
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')
module.exports = {
context: __dirname,
entry: [
'./assets/js/index', // entry point of our app. assets/js/index.js should require other js modules and dependencies it needs
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
],
output: {
path: path.resolve('./assets/bundles/'),
filename: "[name]-[hash].js",
publicPath: 'http://localhost:3000/assets/bundles/', // Tell django to use this URL to load packages and not use STATIC_URL + bundle_name
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(), // don't reload if there is an error
new BundleTracker({filename: './webpack-stats.json'}),
],
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['react-hot-loader/webpack', 'babel-loader?presets[]=react'],
}, // to transform JSX into JS
],
},
resolve: {
modules: ['node_modules', 'bower_components'],
extensions: ['.js', '.jsx']
},
}
index.html
{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Example</title>
</head>
<body>
<div id="react-app"></div>
{% render_bundle 'main' %}
</body>
</html>
index.js
var React = require('react')
var ReactDOM = require('react-dom')
var App = require('./app')
var Hello = React.createClass ({
render: function() {
return (
<h1>
Hello, World!
</h1>
)
}
})
ReactDOM.render(<Hello />, document.gectElementById('react-app'))
I have integrated React with Django, trying to setup hot-reload. However the error doesn't seem to be with any of django or react. Probably I'm missing something with webpack-dev-server.

How to use static js generated throught webpack for react app with es6

I am new to es6/react js and webpack and from last 6 days I am trying to create startkit for react app with es6 and webpack below is my webpack.config.js , I am successfully able to configure web pack dev server. My app is running on http:/localhost:8080/webpack-dev-server. When I am running npm build to generate bundle.js. if I am running my app only using localhost:8080 my app is running in chrome but giving error in mozilla (r.render is not function). Webpack is very confusing... Can we run file bundle.js file locally on file:// server. means like in normal html file if I include that bundle.js file it should work right?
My webpack.config.js
var path = require('path');
var webpack = require('webpack');
//var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
var mainPath = path.join(__dirname, 'app', 'index.js');
var buildPath = path.join(__dirname, 'dist/assets/');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var autoprefixer = require('autoprefixer')
var sassLoaders = [
'css-loader?sourceMap',
'postcss-loader',
'sass-loader?sourceMap&includePaths[]=' + path.join(__dirname, './app')
]
module.exports = {
// Makes sure errors in console map to the correct file
// and line number
devtool: 'cheap-module-source-map',
entry: {
'vendor': ['react','react-dom'],
"bundle":mainPath
},
module: {
loaders: [
{
test: [/\.js$/],
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
},
// //{ test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
// { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
// { test: /\.s?css$/, loaders: ['style', 'css', 'sass','css?sourceMap', 'sass?sourceMap'] }
{ test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader', sassLoaders.join('!'))
},
{ test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, loader: 'file-loader?name=/fonts/[name].[ext]' }
]
},
output: {
// We need to give Webpack a path. It does not actually need it,
// because files are kept in memory in webpack-dev-server, but an
// error will occur if nothing is specified. We use the buildPath
// as that points to where the files will eventually be bundled
// in production
path: buildPath,
filename: '[name].js',
publicPath: 'http://localhost:8080/assets'
},
plugins: [
// Pro-tip: Order matters here.
new ExtractTextPlugin('[name].css'), new webpack.optimize.CommonsChunkPlugin(['bundle', 'vendor'], '[name].js')
],
postcss: [
autoprefixer({
browsers: ['last 2 versions'],
//path: "./dist",
filename: '[name].js',
// Everything related to Webpack should go through a build path,
// localhost:8080/build. That makes proxying easier to handle
publicPath: '/dist/'
})
],
resolve: {
extensions: ['', '.js', '.jsx','.sass','.woff','.ttf','.eot','.svg'],
root: [path.join(__dirname, './app')]
},
watch:true
};
my index.html
<!DOCTYPE html>
<html>
<head>
<title>React Home Page</title>
<link rel="stylesheet" href="assets/bundle.css" />
</head>
<body>
<div id="react-app"></div>
<script type="text/javascript" src="assets/vendor.js"></script>
<script type="text/javascript" src="assets/bundle.js"></script>
</body>
</html>
You don't have to link it yourself, webpack does that for you.
the HtmlWebpackPlugin will make sure that the bundle is being linked in the file that you configure.
var path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./app/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index_bundle.js"
},
module: {
rules: [
{ test: /\.(js)$/, use: "babel-loader" },
{ test: /\.css$/, use: ["style-loader", "css-loader"] }
]
},
plugins: [
new HtmlWebpackPlugin({
template: "app/index.html"
})
]
};

fixing relative paths with css-loader and react-router

I can't figure out how to configure webpack to produce css with valid urls no matter the current application url. Here's my project structure:
/theme
/assets
/css
/fonts
/images
/js
/dist
bundle.js
index.html
/node_modules
/src
/test
package.json
webpack.config.js
The /theme directory is a bootstrap theme. The urls in the css are relative. For example:
/* /theme/assets/css/ace-fonts.css */
#font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 300;
src: local('Open Sans Light'), local('OpenSans-Light'), url(../fonts/OpenSans-300.woff) format('woff');
}
#font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(../fonts/OpenSans-400.woff) format('woff');
}
When I visit my application at it's root url(http://localhost:8080/) or a url with a single segment(http://localhost:8080/about) everything works. Those relative urls get resolved to the base url. However, if i refresh the browser while on a 2+ segment url(http://localhost:8080/some/thing) the browser ends up requesting the following url:
http://localhost:8080/some/db812d8a70a4e88e888744c1c9a27e89.woff
React router ends up architecting the right markup for the url, yet the urls in the stylesheets are relative, thus breaking. I'm new to webpack and have no idea how to go about fixing this.
Here's my webpack config:
var path = require('path');
var webpack = require('webpack');
var prodPlugins = [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin()
];
var defaultPlugins = [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.$": "jquery",
"window.jQuery": "jquery"
}),
new webpack.HotModuleReplacementPlugin()
];
module.exports = {
  entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./src/index.js'
],
  output: {
path: 'dist',
filename: 'bundle.js'
},
devServer: {
contentBase: './dist',
hot: true
},
resolve: {
root: path.resolve('./')
},
  module: {
    loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'react-hot!babel'
},
{
test: /\.css$/,
loader: 'style!css!resolve-url'
},
{ test: /\.less$/, loader: "style!css!less"},
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" },
{ test: /\.(png|jpg)$/, loader: 'url?limit=8192' }
]
  },
resolveUrlLoader: {
absolute: true
},
plugins: process.env.NODE_ENV === 'production' ? prodPlugins.concat(defaultPlugins) : defaultPlugins,
};
Any help would be much appreciated.
I ended up using the extract-text-webpack-plugin to put my css file at the root path. That fixed my relative paths in my css files problem but then I noticed the paths of images referenced in my components weren't correct so per #lux's suggestion i set my publicPath to /. Here is my updated webpack.config.js
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var prodPlugins = [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin()
];
var defaultPlugins = [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.$": "jquery",
"window.jQuery": "jquery"
}),
new webpack.HotModuleReplacementPlugin(),
new ExtractTextPlugin('styles.css')
];
module.exports = {
  entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./src/index.js'
],
  output: {
path: 'dist',
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
contentBase: './dist',
hot: true
},
resolve: {
root: path.resolve('./')
},
  module: {
    loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'react-hot!babel'
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
},
{ test: /\.less$/, loader: "style!css!less"},
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url?limit=10000&mimetype=application/font-woff" },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" },
{ test: /\.(png|jpg)$/, loader: 'url?limit=8192' }
]
  },
resolveUrlLoader: {
absolute: true
},
plugins: process.env.NODE_ENV === 'production' ? prodPlugins.concat(defaultPlugins) : defaultPlugins,
};
Because i'm extracting the css to a styles.css file, I had to update my dist/index.html file.
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>My App</title>
<link rel="stylesheet" type="text/css" href="/styles.css">
</head>
<body class="no-skin">
<div id="app"></div>
<script src="/bundle.js"></script>
</body>
</html>

Resources