Webpack config to consume an API with no CORS header - reactjs

I need to consume a public API with no CORS header in it. I'm very new in webpack so i take this approach by readind articles. The scaffolding is provided by the company. This is a second part from a exercise for a job.
I been looking for hours and nothing seems to help. I always get the same response No 'Access-Control-Allow-Origin' header is present on the requested resource ...
This is my webpack.config.js at the moment
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
template: './client/index.html',
filename: 'index.html',
inject: 'body'
})
module.exports = {
entry: './client/index.js',
output: {
path: path.resolve('dist'),
filename: 'index_bundle.js'
},
module: {
rules: [
{ test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{ test: /\.jsx$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.(sass)$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "sass-loader"
}]
},
{
test: /\.html/,
loader: 'raw-loader'
},
],
},
plugins: [HtmlWebpackPluginConfig],
devServer: {
contentBase: './src/public',
port: 1184,
proxy: {
'https://api.mcmakler.de/v1/advertisements': {
target: 'https://api.mcmakler.de/v1/advertisements',
secure: false
}
}
},
resolve: {
extensions: [ '.js', '.jsx' ]
}
};
my dependecies are:
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.9",
"eslint": "^4.0.0",
"file-loader": "^1.1.8",
"html-webpack-plugin": "^2.28.0",
"node-sass": "^4.7.2",
"raw-loader": "^0.5.1",
"sass-loader": "^6.0.6",
"style-loader": "^0.20.2",
"url-loader": "^0.6.2",
"webpack": "^2.6.1",
"webpack-dev-server": "^2.4.5"
},
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0",
"yarn": "^1.3.2"
}
and this is my jsx file which is a simple component to render an advertisement
import React from 'react';
import House from './index.jsx';
const publicApi = "https://api.mcmakler.de/v1/advertisements";
export default class Dinamic extends React.Component {
constructor () {
super();
this.state = {
advertisements: [],
};
}
componentDidMount() {
fetch(publicApi)
.then((results) => {
console.info('results: ', results);
return results.blob();
})
.then ((data) => {
console.info('data: ', data);
const advertisements = data.results.map((ad) => {
return (
<div key="ads.results" >
<p>{ad.title}</p>
</div>
)
});
this.setState({ advertisements });
})
.catch((err) => {
console.error("boom!: ", err);
})
}
render() {
return (
<div className="container-fluid">
<div className="container">
<h1>Dinamic</h1>
<div className="row">
{this.state.advertisements}
</div>
</div>
</div>
);
}
}
Did i miss something important or this is completely wrong?
Disclaimer: The job is for Web UI developer, but i think this is also fun to learn

The browsers don't allow reading forbidden headers like 'set-cookie' from response and browser also does not allow setting 'Cookie' header. So I resolved this issue by reading cookie in onProxyRes method and saving it in a variable and setting the saved cookie on following request in onProxyReq method.
let cookie;
devConfig.devServer = {
proxy: {
'*': {
target: https://target.com,
secure: false,
changeOrigin: true,
onProxyReq: (proxyReq) => {
proxyReq.setHeader('Cookie', cookie);
},
onProxyRes: (proxyRes) => {
Object.keys(proxyRes.headers).forEach((key) => {
if (key === 'set-cookie' && proxyRes.headers[key]) {
const cookieTokens = split(proxyRes.headers[key], ',');
cookie = cookieTokens.filter(element => element.includes('JSESSIONID')).join('');
}
});
},
},
},
}

Related

ModuleParseError with NextJs

I try to migrate my app created with create-react-app to nextJs, and I got always this error :
[ error ] ./src/sass/common.scss
ModuleParseError: Module parse failed: Unexpected character '' (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
and here my file next.config.js :
const withPlugins = require("next-compose-plugins");
const withBundleAnalyzer = require("#next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true"
});
const withSass = require("#zeit/next-sass");
const withCSS = require("#zeit/next-css");
const withImages = require("next-images");
module.exports = withPlugins(
[withBundleAnalyzer, withImages, withSass, withCSS],
{
webpack(config, { buildId, dev, isServer, defaultLoaders, webpack }) {
config.module.rules.push({
test: /\.(png|woff|woff2|eot|ttf|svg|jpg|gif)$/,
use: [
defaultLoaders.babel,
{
loader: "url-loader",
options: {
limit: 100000,
name: "[name].[ext]"
}
}
]
});
return config;
}
});
and my package.json :
"devDependencies": {
"css-loader": "^3.4.2",
"cypress": "^3.1.0",
"file-loader": "^5.0.2",
"node-sass": "^4.13.1",
"redux-devtools": "^3.5.0",
"sass-loader": "^8.0.2",
"url-loader": "^3.0.0"
}
I don't understand... I have a loader for file scss, if someone could explain to me, thanks you!
You didn't add loader for SCSS file type. You can do it like this:
config.module.rules.push({
test: /\.(scss)$/,
loaders: [
{
loader: 'css-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
},
{
loader: 'sass-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
},
],
});
Here I use two loaders. sass-loader convert your SCSS to CSS, then run through css-loader to process #import(), url(), etc.
Don't forget to install these two loaders using npm install.

Configuring next.config file

I am using Next.js and want to add the react-semantic-ui, to use one of their login components.
On the front-end I am getting this error:
Failed to compile
./node_modules/semantic-ui-css/semantic.min.css
ModuleParseError: Module parse failed: Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
This is the login component:
import React from 'react'
import { Button, Form, Grid, Header, Image, Message, Segment } from 'semantic-ui-react'
const Login = () => (
/* login JSX markup */
)
export default Login
This is my next.config.js
module.exports = {
webpack: (config, { dev }) => {
config.module.rules.push(
{
test: /\.css$/,
loader: 'style-loader!css-loader'
},
{
test: /\.s[a|c]ss$/,
loader: 'sass-loader!style-loader!css-loader'
},
{
test: /\.(png|svg|eot|otf|ttf|woff|woff2)$/,
use: {
loader: "url-loader",
options: {
limit: 100000,
publicPath: "./",
outputPath: "static/",
name: "[name].[ext]"
}
}
},
{
test: [/\.eot$/, /\.ttf$/, /\.svg$/, /\.woff$/, /\.woff2$/],
loader: require.resolve('file-loader'),
options: {
name: '/static/media/[name].[hash:8].[ext]'
}
}
)
return config
}
}
const withCSS = require('#zeit/next-css')
module.exports = withCSS()
This is my package.js
{
"name": "create-next-example-app",
"scripts": {
"dev": "nodemon server/index.js",
"build": "next build",
"start": "NODE_ENV=production node server/index.js"
},
"dependencies": {
"#zeit/next-css": "^1.0.1",
"body-parser": "^1.18.3",
"cors": "^2.8.5",
"express": "^4.16.4",
"mongoose": "^5.4.19",
"morgan": "^1.9.1",
"next": "^8.0.3",
"react": "^16.8.4",
"react-dom": "^16.8.4",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.86.0"
},
"devDependencies": {
"css-loader": "^2.1.1",
"file-loader": "^3.0.1",
"node-sass": "^4.11.0",
"nodemon": "^1.18.10",
"sass-loader": "^7.1.0",
"url-loader": "^1.1.2"
}
}
I read somewhere you have to include a _document.js in the pages directory.
// _document is only rendered on the server side and not on the client side
// Event handlers like onClick can't be added to this file
// ./pages/_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<Html>
<Head>
<link rel='stylesheet'
href='//cdn.jsdelivr.net/npm/semantic-ui#2.4.2/dist/semantic.min.css'
/>
</Head>
<body className="custom_class">
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
Is this really this hard?
Update
There is an alternate way of getting this to work.
When you start up your Next app you get a components folder which includes a head.js and a nav.js file.
The head.js file ultimately is analogous to a <head></head> tag in HTML. Or I should say that's what the head.js compiles to. ANYWAY, you can just add this in there:
<link
rel="stylesheet"
href="//cdn.jsdelivr.net/npm/semantic-ui#2.4.2/dist/semantic.min.css"
/>
and that will work.
But like I said you still can't import the modules like so:
import 'semantic-ui-css/semantic.min.css'
In case someone uses next-compose-plugins and getting the above error, here's a fix:
const withCSS = require('#zeit/next-css');
const withImages = require('next-images');
const withPlugins = require('next-compose-plugins');
// fix: prevents error when .css files are required by node
if (typeof require !== 'undefined') {
require.extensions['.css'] = (file) => {};
}
const nextConfig = {
target: 'server',
webpack: (config, { dev }) => {
config.module.rules.push({
test: /\.(raw)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: 'raw-loader'
});
return config;
}
};
module.exports = withPlugins([withImages, withCSS({target: 'serverless',
webpack (config) {
config.module.rules.push({
test: /\.(png|svg|eot|otf|ttf|woff|woff2)$/,
use: {
loader: 'url-loader',
options: {
limit: 8192,
publicPath: '/_next/static/',
outputPath: 'static/',
name: '[name].[ext]'
}
}
})
return config
}})], nextConfig);
So it looks like I had to do the following to get this to work:
Changing my next.config.js file to:
const withCSS = require('#zeit/next-css')
module.exports = withCSS({
webpack: function (config) {
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}
}
})
return config
}
})
And doing an npm i css-loader file-loader url-loader -D did the trick.
However I'm baffled as to why css-loader file-loader are needed? I'm used to webpack configs where you are explicitly adding the loaders (Like we are adding the url-loader above)... I didn't have to here!

Cannot start react module

Getting the following exception when starting the npm.
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.module has an unknown property 'loaders'. These properties are valid:
object { exprContextCritical?, exprContextRecursive?, exprContextRegExp?, exprContextRequest?, noParse?, rules?, defaultRules?, unknownContextCritical?, unknownContextRecursive?, unknownContextRegExp?, unknownContextRequest?, unsafeCache?, wrappedContextCritical?, wrappedContextRecursive?, wrappedContextRegExp?, strictExportPresence?, strictThisContextOnImports? }
-> Options affecting the normal modules (NormalModuleFactory).
var path= require('path');
module.exports = {
entry : './script.jsx',
output : {
path : path.resolve(__dirname,''),
filename: 'transpiled.js'
},
module : {
loaders: [
{
test:/\.jsx?$/,
loaders:'babel-loader',
exclude : /node_modules/,
query : {
presets : ['es2015','react']
}
}
]
}
}
After the updations the code is running but react components are not getting rendered on the screen.
//Update
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test title</title>
</head>
<body>
<div id ="content">
<h1>This is the demo of your web page</h1>
</div>
<script src ="transpiled.js"></script>
</body>
</html>
//webpack config
var path= require('path');
module.exports = {
entry : './script.jsx',
output : {
path : path.resolve(__dirname,'react/index.html'),
filename: 'transpiled.js'
},
module : {
rules: [ // rules rules
{
test: /\.jsx?$/,
loaders: 'babel-loader',
//use:'babel-loader', // use here
exclude : /node_modules/,
query : {
presets : ['es2015','react']
}
}
]
}
}
//script.jsx
import React from 'react';
import ReactDOM from 'react-dom';
class MyComponent extends React.Component {
render() {
return (
<h2>Hello World !!!</h2>
);
}
}
ReactDom.render(
<MyComponent/>,document.getElementById('content')
);
//package.json
{
"name": "reactjs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"it": "webpack-dev-server --hot"
},
"author": "chetan",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.4",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"webpack": "^4.5.0",
"webpack-cli": "^2.0.14",
"webpack-dev-middleware": "^3.1.2",
"webpack-dev-server": "^3.1.3",
"webpack-hot-middleware": "^2.21.2"
},
"dependencies": {
"react": "^16.3.1",
"react-dom": "^16.3.1",
"webpack-sources": "^1.1.0"
}
}
You need to replace keyword loaders to keyword rules. And in each rules object replace loaders to keyword use.
module.exports = {
entry : './script.jsx',
output : {
path : path.resolve(__dirname,''),
filename: 'transpiled.js'
},
module : {
rules: [ // rules rules
{
test:/\.jsx?$/,
use:'babel-loader', // use here
exclude : /node_modules/,
query : {
presets : ['es2015','react']
}
}
]
}
}
Edit
Now your component not rendered on the screen because output.path in webpack config incorrect. It should be like this:
output : {
path : path.resolve(__dirname),
filename: 'transpiled.js'
}
Because script tag in your html reference in root of the project:
<script src="transpiled.js"></script>
Your webpack.config file is in the wrong format
var path = require('path');
module.exports = {
entry: './script.jsx',
output: {
path: path.resolve(__dirname, ''),
filename: 'transpiled.js'
},
module: {
rules: [
{
test: /\.jsx?$/,
loaders: 'babel-loader',
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
'#babel/preset-env',
// your preset
]
}
}
]
}
]
}
}
See more here

transpiled code (babel) seems not working in Browser

Hi I'm working on an existing app which needs enhancements. The app is built using angularJS, Babel, webpack. I struggled running the app locally and finally succeeded in running it after making changes to how we call a basedirective (like below) which was using babel next generation javascript notation to regular notation (a compiler is present on babel site to do this).
function filtersDirective() {
return {
...baseDirective(template, FiltersCtrl),
...{
bindToController: {
customers: '=',
regions: '=',
managers: '=',
projects: '=',
statuses: '=',
},
},
}
}
Now the issue is I'm able to run this app locally and also able to build the bundle files (app.bundle.js, vendor.bundle.js, manifest.bundle.js) but when I deploy these files to my test server, the console error is like below.
ReferenceError: production is not defined
at dispatchXhrRequest (vendor.bundle.js:24340)
at new Promise (<anonymous>)
at xhrAdapter (vendor.bundle.js:24325)
at dispatchRequest (vendor.bundle.js:92054)
at <anonymous>
vendor.bundle.js:65932
TypeError: Cannot read property 'map' of undefined
at https://#domain/cdn/3.2.1/vendor.bundle.js:5202:31
at https://#domain/cdn/3.2.1/vendor.bundle.js:5090:28
at f1 (https://#domain/cdn/3.2.1/vendor.bundle.js:5070:27)
at https://#domain/cdn/3.2.1/vendor.bundle.js:4920:35
at https://#domain/cdn/3.2.1/vendor.bundle.js:4920:35
at https://#domain/cdn/3.2.1/vendor.bundle.js:4920:35
at https://#domain/cdn/3.2.1/vendor.bundle.js:4672:27
at getAttributeFromProjects (https://#domain/cdn/3.2.1/app.bundle.js:117:10)
at MainController (https://#domain/cdn/3.2.1/app.bundle.js:127:21)
at invoke (https://#domain/cdn/3.2.1/vendor.bundle.js:58052:17) <div ui-view="" class="ng-scope">
My Traspiled app.bundle.js looks like below
webpackJsonp([1], {
/***/
101:
/***/
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_0_deepmerge__ = __webpack_require__(69);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_0_deepmerge___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_deepmerge__);
const baseConfig = {
title: 'Test Dashboard',
dashboard: {
title: 'Test Report',
subtitle: 'Weekly Highlights'
},
header: {
title: 'Company Confidential',
nav: 'Test'
}
}
let config = baseConfig
if (window.AppConfig) {
if (window.AppConfig.config) {
config = __WEBPACK_IMPORTED_MODULE_0_deepmerge___default.a(baseConfig, window.AppConfig.config)
}
}
const {
title,
dashboard,
header,
statusBar
} = config
/* harmony export (immutable) */
__webpack_exports__["c"] = title;
/* harmony export (immutable) */
__webpack_exports__["a"] = dashboard;
/* unused harmony export header */
/* unused harmony export statusBar */
/* harmony default export */
__webpack_exports__["b"] = (config);
/***/
}),
/***/
222:
/***/
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */
__webpack_require__.d(__webpack_exports__, "b", function() {
return resolve;
});
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_0_ramda__ = __webpack_require__(36);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_0_ramda___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_ramda__);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_1_angular__ = __webpack_require__(7);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_1_angular___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_angular__);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_2__utils__ = __webpack_require__(4);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_3__services_api__ = __webpack_require__(99);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_4__appConfig_config__ = __webpack_require__(101);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_5__dashboard_html__ = __webpack_require__(479);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_5__dashboard_html___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5__dashboard_html__);
/* harmony reexport (default from non-hamory) */
__webpack_require__.d(__webpack_exports__, "c", function() {
return __WEBPACK_IMPORTED_MODULE_5__dashboard_html___default.a;
});
Which is very different from previous version of app.bundle.js which is on prod server which looks like below
webpackJsonp([1], {
/***/
10:
/***/
(function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getWebpartData = undefined;
var _keys = __webpack_require__(124);
var _keys2 = _interopRequireDefault(_keys);
var _deepmerge = __webpack_require__(76);
var _deepmerge2 = _interopRequireDefault(_deepmerge);
var _utils = __webpack_require__(4);
var _majorMilestones = __webpack_require__(501);
var _majorMilestones2 = _interopRequireDefault(_majorMilestones);
var _budget = __webpack_require__(502);
var _budget2 = _interopRequireDefault(_budget);
var _projectRisksAndIssues = __webpack_require__(503);
var _projectRisksAndIssues2 = _interopRequireDefault(_projectRisksAndIssues);
var _actionItems = __webpack_require__(504);
var _actionItems2 = _interopRequireDefault(_actionItems);
var _keyDates = __webpack_require__(505);
var _keyDates2 = _interopRequireDefault(_keyDates);
var _gantt = __webpack_require__(506);
var _gantt2 = _interopRequireDefault(_gantt);
var _statusBar = __webpack_require__(507);
var _statusBar2 = _interopRequireDefault(_statusBar);
var _angular = __webpack_require__(6);
var _angular2 = _interopRequireDefault(_angular);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
below is my package.json file for reference
{
"name": "pmrdashboard",
"version": "3.2.1",
"dependencies": {
"#cgross/angular-notify": "2.5.1",
"angular": "1.4.2",
"angular-bootstrap": "~0.12.2",
"angular-chart.js": "^1.0.1",
"angular-gantt": "^1.2.13",
"angular-google-chart": "^0.1.0",
"angular-messages": "~1.4.2",
"angular-moment": "1.0.1",
"angular-pubsub": "^0.2.0",
"angular-resource": "~1.4.2",
"angular-sanitize": "~1.4.2",
"angular-strap": "^2.3.9",
"angular-toastr": "~1.5.0",
"angular-ui-router": "~0.2.15",
"animate.css": "~3.4.0",
"axios": "^0.16.2",
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-polyfill": "^6.23.0",
"babel-runtime": "^6.23.0",
"bootstrap-sass": "3.3.7",
"chart.js": "2.1.0",
"deepmerge": "^1.3.2",
"echo-loader": "0.0.1",
"jquery": "~2.1.4",
"lodash": "^4.13.1",
"moment": "2.10.6",
"ngsticky-puemos": "^0.0.4",
"node-sass": "4.5.3",
"ramda": "^0.22.1"
},
"scripts": {
"dev": "babel-node scripts/cli.js dev",
"serve": "babel-node scripts/cli.js serve",
"build": "babel-node scripts/cli.js build --upload=false --plugins dynamic-import-node",
"deploy": "babel-node scripts/cli.js build",
"serve:prod": "babel-node scripts/cli.js serve:prod",
"serve:optimize": "babel-node scripts/cli.js serve:prod --optimize=true",
"serve:cdn": "babel-node scripts/cli.js serve:prod --usecdn=true"
},
"devDependencies": {
"babel-eslint": "^7.2.3",
"babel-loader": "^7.0.0",
"babel-plugin-angularjs-annotate": "^0.7.0",
"babel-plugin-dynamic-import-node": "^1.0.2",
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.5.1",
"chalk": "^1.1.3",
"clean-webpack-plugin": "0.1.16",
"cross-env": "^5.1.3",
"css-loader": "0.28.1",
"eslint": "2.13.1",
"eslint-config-angular": "^0.5.0",
"eslint-plugin-angular": "^2.4.0",
"execa": "^0.6.3",
"exports-loader": "0.6.4",
"express": "^4.15.3",
"extract-text-webpack-plugin": "2.1.0",
"file-loader": "0.11.1",
"fs-extra": "^3.0.1",
"html-loader": "0.4.5",
"html-webpack-harddisk-plugin": "0.1.0",
"html-webpack-plugin": "2.28.0",
"http-proxy-middleware": "*",
"http-server": "^0.10.0",
"image-webpack-loader": "3.3.1",
"imports-loader": "0.7.1",
"jshint-loader": "^0.8.4",
"raw-loader": "0.5.1",
"resolve-url-loader": "2.0.2",
"rollup": "^0.43.0",
"rollup-plugin-babel": "^2.7.1",
"rollup-plugin-node-resolve": "^3.0.0",
"sass-loader": "6.0.5",
"shelljs": "^0.7.7",
"ssh-webpack-plugin": "^0.1.7",
"style-loader": "0.17.0",
"svg-loader": "0.0.2",
"url-loader": "0.5.8",
"webpack": "3.0.0",
"webpack-dev-server": "^2.5.0",
"yargs": "^8.0.1"
},
"engines": {
"node": ">=0.10.0"
}
}
webpack config files: it's a folder with .babelrc, dev.js, server.js, prod.js, share.js and below is share.js file
const path = require('path')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {
rm
} = require('shelljs')
const pkg = require('../package.json')
const webpack = require('webpack')
const baseChunks = ['config', 'app']
const basePlugins = (chunks, enableHtml) => {
const html = enableHtml ?
[
new HtmlWebpackPlugin({
title: 'PMR Client',
filename: './index.html',
template: './src/client/index.ejs',
chunksSortMode: (a, b) => chunks.indexOf(a.names[0]) - chunks.indexOf(b.names[0]),
alwaysWriteToDisk: true,
env: process.env.NODE_ENV || 'development',
}),
new HtmlWebpackHarddiskPlugin(),
] :
[]
return [
new ExtractTextPlugin('style.css'),
...html,
new webpack.ProvidePlugin({
'window.jQuery': 'jquery',
}),
new webpack.optimize.ModuleConcatenationPlugin(),
]
}
const baseEntries = {
app: './src/app/index.js',
config: `./clients/${process.env.CLIENT}/config.js`,
}
const baseOutput = () => {
const output = {
path: path.join(__dirname, `../dist/cdn/${pkg.version}`),
filename: '[name].bundle.js',
}
if (process.env.NODE_ENV === 'production' && process.env.UPLOAD === 'true') {
output['publicPath'] = `//streamlinedoffice.com/pmr/cdn/${pkg.version}/`
}
return output
}
const sourceMap = (process.env.NODE_ENV === 'production') ? '' : 'sourceMap'
const getBaseConfig = ({
plugins = [],
chunks = [],
entries = baseEntries,
enableHtml = false
} = {}) => {
rm('-rf', path.resolve(__dirname, '../dist'))
const ch = [...baseChunks, ...chunks]
return {
entry: entries,
output: baseOutput(),
target: 'web',
devtool: 'cheap-module-eval-source-map',
plugins: [...basePlugins(ch, enableHtml), ...plugins],
module: {
rules: [{
test: /\.html$/,
use: [{
loader: 'html-loader',
options: {
minimize: true,
root: '../src/assets/images',
},
}, ],
},
{
test: [/src\/app.*\.js$/, /client.*\.js$/],
exclude: /node_modules/,
use: {
loader: 'babel-loader',
// loader:'echo-loader',
},
},
{
test: [/\.css$/, /\.scss$/],
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', `sass-loader?${sourceMap}`],
}),
},
{
test: /bootstrap-sass\/assets\/javascripts\//,
use: 'imports-loader?jQuery=jquery'
},
// Font Definitions
{
test: /\.svg$/,
loader: 'url-loader?limit=65000&mimetype=image/svg+xml&name=public/fonts/[name].[ext]',
},
{
test: /\.woff$/,
loader: 'url-loader?limit=65000&mimetype=application/font-woff&name=public/fonts/[name].[ext]',
},
{
test: /\.woff2$/,
loader: 'url-loader?limit=65000&mimetype=application/font-woff2&name=public/fonts/[name].[ext]',
},
{
test: /\.[ot]tf$/,
loader: 'url-loader?limit=65000&mimetype=application/octet-stream&name=public/fonts/[name].[ext]',
},
{
test: /\.eot$/,
loader: 'url-loader?limit=65000&mimetype=application/vnd.ms-fontobject&name=public/fonts/[name].[ext]',
},
{
test: /\.png$/,
use: {
loader: 'url-loader?limit=8192',
},
},
{
test: /\.(jpe?g|gif)$/i,
use: [
'file-loader?hash=sha512&digest=hex&publicPath=../&name=./img/[hash].[ext]',
{
loader: 'image-webpack-loader',
query: {
gifsicle: {
interlaced: false,
},
progressive: true,
optipng: {
optimizationLevel: 7,
},
bypassOnDebug: true,
},
},
],
},
],
},
}
}
module.exports = getBaseConfig
Below is the script used to build the app.bundle.js, vendor.bundle.js an d manifest.bundle.js files (this file is on scripts/cmds/prod.js)
import {
echo,
head,
execStrict,
ls,
copy,
rmdir,
mkdir
} from '../utils'
import fs from 'fs-extra'
import path from 'path'
import {
rollup
} from 'rollup'
import resolve from 'rollup-plugin-node-resolve'
import babel from 'rollup-plugin-babel'
const compiler = client =>
rollup({
entry: `./clients/${client}/config.js`,
plugins: [
resolve(),
babel({
exclude: 'node_modules/**',
babelrc: false,
presets: [
['env',
{
modules: false,
targets: {
browsers: [
"last 3 versions",
"Explorer 9",
],
},
},
],
],
plugins: ['external-helpers'],
externalHelpers: true
}),
],
}).then(bundle =>
bundle.write({
format: 'cjs',
dest: path.join(__dirname, `../../.tmpClients/${client}/config.js`),
})
)
const getClients = () =>
fs
.readdirSync('./clients')
.filter(file => fs.lstatSync(path.join('./clients', file)).isDirectory())
const handleCommand = async ({
upload = true,
optimize = true
}) => {
echo(head('Building clients...'))
const clients = getClients()
mkdir('./.tmpClients')
const promises = clients.map(client => {
compiler(client)
})
await Promise.all(promises)
echo(head('Run production build'))
await execStrict(
`cross-env UPLOAD=${upload} OPTIMIZE=${optimize} NODE_ENV=production webpack --config webpack/prod.js --progress --colors --define process.env.NODE_ENV="'production'"`
)
echo(head('Copying config files to clients'))
ls('./.tmpClients').forEach(client => {
copy({
origin: `./.tmpClients/${client}/*.js`,
dest: `./dist/clients/${client}`,
})
copy({
origin: `./dist/clients/${client}/index.html`,
dest: `./dist/clients/${client}/default.aspx`,
})
copy({
origin: './src/client/favicon.ico',
dest: `./dist/clients/${client}/`,
})
})
rmdir('./.tmpClients')
}
exports.command = 'build'
exports.describe = 'Create a production build'
exports.handler = handleCommand
exports.builder = {
upload: {
describe: 'Upload the production files to the cdn',
type: 'boolean',
default: true,
},
optimize: {
describe: 'Toggle the production optimizations, useful to check the production build as development',
type: 'boolean',
default: true,
},
}
below is .babelrc in webpack folder:
{
"presets": ["env"],
"plugins": ["transform-object-rest-spread", "dynamic-import-node"]
}
below .babelrc is in global same level as webpack folder
{
"presets": [
["env", {
"targets": {
"browsers": ["last 3 versions","Explorer 9"]
}
}]
],
"plugins": ["transform-runtime", "transform-object-rest-spread",
["angularjs-annotate", {
"explicitOnly": true
}]]
}
if anyone ran into such similar issue are know how to resolve it do share your inputs. Any help is much appreciated. Thanks

webpack react bundle file is huge

Im trying to build react app using webpack as bundle tool.
the output bundle is huge. here is my webpack settings:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const merge = require('webpack-merge');
const validate = require('webpack-validator');
const parts = require('./libs/parts');
const PATHS = {
app:path.join(__dirname.toLowerCase(),'shared'),
build:path.join(__dirname.toLowerCase(),'build'),
//css:path.join(__dirname.toLowerCase(),'client','main.css')
css:[
//path.join(__dirname,'node_modules','purecss'),
//path.join(__dirname,'client','client.less'),
path.join(__dirname,'client','client.less')
]
};
const common = {
entry:{
app:PATHS.app,
style:PATHS.css
},
output:{
path:PATHS.build,
filename:'[name].js',
},
/*plugins:[
new HtmlWebpackPlugin({
title:"Webpack to pack the whole web",
template:"client/index.html"
})
]*/
};
var config;
switch (process.env.npm_lifecycle_event) {
case "build":
config = merge(common,
{
devtool: 'cheap-module-source-map',
output: {
path: PATHS.build,
filename: '[name].js',
// This is used for require.ensure. The setup
// will work without but this is useful to set.
chunkFilename: '[chunkhash].js'
}
},
parts.clean(PATHS.build),
parts.setFreeVariable(
'process.env.NODE_ENV',
'production'
),
parts.supportESSix(PATHS.app),
parts.extractBundle({
name: 'vendor',
entries: ['react','react-dom','react-router','react-addons-pure-render-mixin',
'redux','react-redux','immutable',"redux-thunk","superagent"]
}),
parts.purifyCSS(PATHS.css),
parts.setupLess(PATHS.css),
parts.minify(),
parts.compressBundle()
);
break;
default:
config = merge(common,
{
devtool: 'source-map',
output: {
path: PATHS.build,
filename: '[name].js',
// This is used for require.ensure. The setup
// will work without but this is useful to set.
chunkFilename: '[chunkhash].js'
}
},
parts.clean(PATHS.build),
parts.setFreeVariable(
'process.env.NODE_ENV',
'production'
),
parts.supportESSix(PATHS.app),
parts.extractBundle({
name: 'vendor',
entries: ['react','react-dom','react-router','react-addons-pure-render-mixin',
'redux','react-redux','immutable',"redux-thunk","superagent"]
}),
parts.purifyCSS(PATHS.css),
parts.setupLess(PATHS.css),
parts.minify()
);
}
module.exports = validate(config);
the parts.js file which run specific task:
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PurifyCSSPlugin = require('purifycss-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
exports.devServer=function(options){
return {
devServer:{
historyApiFallback:true,
hot:true,
inline:true,
stats:'errors-only',
host:options.host,
port:options.port
},
plugins:[
new webpack.HotModuleReplacementPlugin({
multiStep:true
})
]
};
};
exports.setupCSS=function(paths) {
return {
module:{
loaders:[
{
test: /\.css$/,
loaders: ['style', 'css'],
include: paths
}
]
}
};
};
//minify output
exports.minify=function(){
return {
plugins:[
new webpack.optimize.UglifyJsPlugin({
beautify:false,
comment:false,
compress:{
warnings:false,
drop_console:true
}
})
]
}
};
exports.setFreeVariable = function(key, value) {
const env = {};
env[key] = JSON.stringify(value);
return {
plugins: [
new webpack.DefinePlugin(env)
]
};
}
exports.extractBundle = function(options) {
const entry = {};
entry[options.name] = options.entries;
return {
// Define an entry point needed for splitting.
entry: entry,
plugins: [
// Extract bundle and manifest files. Manifest is
// needed for reliable caching.
new webpack.optimize.CommonsChunkPlugin({
names: [options.name, 'manifest']
})
]
};
}
exports.clean = function(path) {
return {
plugins: [
new CleanWebpackPlugin([path], {
// Without `root` CleanWebpackPlugin won't point to our
// project and will fail to work.
root: process.cwd()
})
]
};
}
exports.extractCSS = function(paths) {
return {
module: {
loaders: [
// Extract CSS during build
{
test:/\.less$/,
loader: ExtractTextPlugin.extract('style','css'),
include: paths
}
]
},
plugins: [
// Output extracted CSS to a file
new ExtractTextPlugin('[name].[chunkhash].css')
]
};
}
exports.purifyCSS = function(paths) {
return {
plugins: [
new PurifyCSSPlugin({
basePath: process.cwd(),
// `paths` is used to point PurifyCSS to files not
// visible to Webpack. You can pass glob patterns
// to it.
paths: paths
}),
]
}
}
exports.setupLess=function(path) {
return {
module:{
loaders:[
{
test:/\.less$/,
loader:ExtractTextPlugin.extract('style-loader','css-loader!less-loader'),
include:path
},
{ test: /\.(ttf|eot|svg)$/, loader: "file-loader" },
{test: /\.eot$/, loader: "file" },
{ test: /\.(woff|woff2)$/, loader: "url?limit=10000&minetype=application/font-woff" }
]
},
plugins: [
// Output extracted CSS to a file
new ExtractTextPlugin('style.css')
]
}
};
exports.supportESSix=function(path) {
return {
module:{
loaders:[
{
test:/\.js$/,
loader:"babel",
include:path,
exclude:"node_modules"
}
]
}
};
};
exports.compressBundle=function(){
return {
plugins: [
new CompressionPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.html$/,
threshold: 10240,
minRatio: 0.8
})
]
}
}
These are dependencies packages:
"dependencies": {
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-preset-es2015": "^6.14.0",
"babel-preset-react": "^6.11.1",
"body-parser": "^1.15.2",
"compress": "^0.99.0",
"cookie-parser": "^1.4.3",
"csurf": "^1.9.0",
"es6-promise": "^3.2.1",
"express": "^4.14.0",
"express-jwt": "^5.0.0",
"express-session": "^1.14.1",
"form-data": "^2.0.0",
"history": "^3.2.1",
"immutable": "^3.8.1",
"isomorphic-fetch": "^2.2.1",
"jsonwebtoken": "^7.1.9",
"method-override": "^2.3.6",
"mongoose": "^4.6.0",
"passport": "^0.3.2",
"passport-facebook": "^2.1.1",
"password-hash": "^1.2.2",
"q": "^1.4.1",
"react": "^15.3.2",
"react-addons-pure-render-mixin": "^15.3.1",
"react-dom": "^15.3.1",
"react-redux": "^4.4.5",
"react-router": "^2.7.0",
"redux": "^3.6.0",
"redux-immutable": "^3.0.8",
"redux-thunk": "^2.1.0",
"sanitize-html": "^1.13.0",
"superagent": "^2.3.0"
},
but the output is really big:
Question:
anything wrong with my webpack config ?
is that normal for this bundle size ?
3.if not. How do I get smaller size of this bundle?
Thank you.

Resources