Search code examples
node.jsvue.jsvuejs2node-webkitnw.js

NW.js child_process not working with vue.js app


I want to build a vue.js app with node webkit (Nw.js).

The app has to exec a binary so I did

const exec = require("child_process").exec;
  exec(
    '"C:\\someBin.exe" /someOptions',
    (e, stdout, stderr) => {
      if (e instanceof Error) {
        console.error(e);
        throw e;
      }
      console.log("stdout ", stdout);
      console.log("stderr ", stderr);
    }
  );

I tried with .exec or .spawn but I always get some strange errors like :

TypeError: (0 , n(...).exec) is not a function

It has to be linked with me using vue.js because when I test this code in a simple node webkit app with just a script tag, it works !

Is there some kind of incompatibility between webpack (used by vue.js) and the require keyword of nodejs ?

When printing the content of require("child_process") there's a few things but nothing of what I would expect (no spawn or exec methods). It seems that the require itself is not working for this specific case. But odly it still works for other npm packages that have been installed.

To create the app I use "npm run build" which generates the final files directly in the /dist directory. In this directory I have put the node webkit files so I can just run the node webkit binary from there.


Solution

  • Finally I found the solution.

    It seems that webpack overwrites some node modules.

    To prevent this you just have to add this to your webpack config :

    target: 'node-webkit',
    

    I read that there were other types of availble targets like "node".

    This is most of the webpack file to help you place the above line correctly.

    module.exports = {
      context: path.resolve(__dirname, '../'),
      entry: {
        app: './src/main.js'
      },
      output: {
        path: config.build.assetsRoot,
        filename: '[name].js',
         publicPath: process.env.NODE_ENV === 'production'
          ? config.build.assetsPublicPath
          : config.dev.assetsPublicPath
      },
      resolve: {
        extensions: ['.js', '.vue', '.json'],
        alias: {
          'vue$': 'vue/dist/vue.esm.js',
          '@': resolve('src'),
        }
      },
      module: {
        rules: [
          ...(config.dev.useEslint ? [createLintingRule()] : []),
          {
            test: /\.vue$/,
            loader: 'vue-loader',
            options: vueLoaderConfig
          },
          {
            test: /\.js$/,
            loader: 'babel-loader',
            include: [resolve('src'), resolve('test'), 
    resolve('node_modules/webpack-dev-server/client')]
           },
          {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            loader: 'url-loader',
            options: {
              limit: 10000,
              name: utils.assetsPath('img/[name].[hash:7].[ext]')
            }
          },
          {
            test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
            loader: 'url-loader',
            options: {
              limit: 10000,
              name: utils.assetsPath('media/[name].[hash:7].[ext]')
            }
          },
          {
            test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
            loader: 'url-loader',
            options: {
              limit: 10000,
              name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
            }
          }
        ]
      },
      target: 'node-webkit'
    }