6

Hope you are all well :)

I was working on a REST API server with Nodejs and after completing an alpha version, I wanted to create a bundle for it with build tools, Although I succeeded at some point in bundling the app still could not make the Express Rest API scripts to be bundled. As I am not really experienced with the Webpack, I am pretty sure that I am doing something wrong and there has to be a way to do this. You can also see my my webpack.config.js, .babelrc and package.json below:

Webpack.config.js

var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var module_dir = `${__dirname}/node_modules`;
const path = require('path');

module.exports = {
  entry: {
    app: [
      'babel-polyfill',
      './index.js',
    ],
  },
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'app.bundle.js',
  },
  module: {
    rules: [{
        test: /\.js?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
           presets: ['env', 'stage-0']
        }
    }]
  },
  resolveLoader: {
    modules: [
          __dirname + '/node_modules'
        ]
  }
}

.Babelrc

{
    "presets": ["@babel/env"]
}

package.json

{
  "name": "",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "nodemon index.js",
    "build": "webpack --mode production --progress"
  },
  "keywords": [
    "log",
    "npm",
    "node",
    "rest",
    "api",
    "debug",
    "bug"
  ],
  "author": "Mehdi Roshan Fekr",
  "license": "ISC",
  "dependencies": {
    "@babel/core": "^7.3.4",
    "@babel/preset-env": "^7.3.4",
    "express": "^4.16.4",
    "joi": "^14.3.1",
    "nodemon": "^1.18.10"
  },
  "devDependencies": {
    "@babel/core": "^7.1.6",
    "@babel/preset-env": "^7.1.6",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.4",
    "webpack": "^4.25.1",
    "webpack-cli": "^3.1.2"
  }
}

I also have read this article about using express with webpack but I couldn't implement it properly, which I think one the reason for, is it is for a ReactJS app: How can I use webpack with express?

----Updates-----

Error

ERROR in ./index.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find module 'babel-preset-env' from 'C:\Projects\# App Projects\Qcentic-Log'
- Did you mean "@babel/env"?
    at Function.module.exports [as sync] (C:\Projects\# App Projects\Qcentic-Log\node_modules\resolve\lib\sync.js:58:15)
    at resolveStandardizedName (C:\Projects\# App Projects\Qcentic-Log\node_modules\@babel\core\lib\config\files\plugins.js:101:31)
    at resolvePreset (C:\Projects\# App Projects\Qcentic-Log\node_modules\@babel\core\lib\config\files\plugins.js:58:10)
    at loadPreset (C:\Projects\# App Projects\Qcentic-Log\node_modules\@babel\core\lib\config\files\plugins.js:77:20)
    at createDescriptor (C:\Projects\# App Projects\Qcentic-Log\node_modules\@babel\core\lib\config\config-descriptors.js:154:9)
    at items.map (C:\Projects\# App Projects\Qcentic-Log\node_modules\@babel\core\lib\config\config-descriptors.js:109:50)

index.js

const express = require('express');
const app = express();
const CustomModule = require('./CustomModule');
app.use(express.json());
//My Endpoints...
app.listen(80, () => console.log('Listening on port 80'));
Mehdi Amenein
  • 937
  • 9
  • 23
  • 1
    To bundle for nodejs, you need to add `target: "node"` to your config. And if that is not enough, please do post the errors/warning or anything that can help debugging, otherwise it's just guessing. – Pavel Denisjuk Mar 13 '19 at 09:23
  • Thank you for your comment, I have updated the question and added the index.js general structure and the error that I get – Mehdi Amenein Mar 13 '19 at 10:58

1 Answers1

3

Since you are passing babel config directly to the loader, you do not need the .babelrc file. Also, you are using babel v7, so below is the updated config (your config and package.json contain mixed packages of babel v6 and v7 and they don't work together):

module.exports = {
    target: "node",
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'app.bundle.js',
    },
    module: {
        rules: [{
            test: /\.js?$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
                presets: [
                    [
                        "@babel/preset-env",
                        {
                            targets: {
                                node: "8.10"
                            }
                        }
                    ]
                ]
            }
        }]
    },
    resolveLoader: {
        modules: [
            __dirname + '/node_modules'
        ]
    }
}
  1. Note that I removed @babel/polyfill, you don't need it for the server environment (I am sure because I am also bundling my server code with webpack and never needed it).

  2. Make sure to set the version of node to whatever your target version is.

  3. Also note that query is a very old way of passing options to webpack loaders, so I updated it to the new syntax, using options. And it is always best to pass full name of babel plugins, e.g.: @babel/preset-env instead of just env. The old way of resolving plugin names would generate a babel-preset-env based on env, but since babel v7 they restructured the project to "scoped packages", thus the @babel/ prefix, so best to specify full name.
Pavel Denisjuk
  • 1,475
  • 12
  • 13
  • Thank you so much for your answer, the bundle was successful but I get error when I try to use it on apache: I did make a very simple html for it like below: Hellow but it does not load anything – Mehdi Amenein Mar 13 '19 at 12:07
  • app.bundle.js:88 Uncaught ReferenceError: require is not defined – Mehdi Amenein Mar 13 '19 at 12:09
  • I removed the api endpoints and just put a simple console log in the index but still got the same error – Mehdi Amenein Mar 13 '19 at 12:10
  • 1
    Once bundled, you need to run your express server like `node app.bundle.js`. It will start your express server and the API will be ready to receive requests. – Pavel Denisjuk Mar 13 '19 at 12:15
  • yes but server is based on php and is running uner apache, these api endpoints are going to be an addition like a micro service there and if it is possible they should be callable from browser directly with out running a new node – Mehdi Amenein Mar 13 '19 at 12:17
  • APIs can not be run in the browser. What you are trying to do is including a javascript bundle containing your API in the browser. – Pavel Denisjuk Mar 13 '19 at 12:20
  • I'm sorry I think I mis explained the running concept of the nodejs app What I meant was somthing like this: http://www.codingtricks.biz/run-nodejs-application-apache/ Also thank you so much, your a legend :) – Mehdi Amenein Mar 13 '19 at 12:43
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/189949/discussion-between-pavel-denisjuk-and-mehdi-roshan-fekr). – Pavel Denisjuk Mar 13 '19 at 12:48
  • @PavelDenisjuk Thank you man! +1! The only change I had to do is in my code. I was getting "TypeError: Cannot assign to read only property 'exports' of object '#'", then have done what's said here: https://github.com/webpack/webpack/issues/4039#issuecomment-273890888: change 'module.exports' for 'export default' and it worked as a charm. I believe that's not a solution but a workaround. Any chance you know why and how to solve it without replacing 'module.exports'? – Rodrigo.A92 Mar 07 '20 at 05:07
  • @Rodrigo.A92 without looking at your code I can't tell you what's wrong, but most likely it's an issue with mixing import/export and module.exports. Use one of the systems, but not both at the same time. – Pavel Denisjuk Mar 08 '20 at 09:18
  • @PavelDenisjuk Thanks for the answer. I'll investigate further and if I'm not able to find a proper answer, will post a new thread. Thanks for the help! – Rodrigo.A92 Mar 09 '20 at 12:24