JIACHENG

How to Run Node.js in a Browser [Tutorial]

"Browser based bundler" is a very interesting topic.

For example, can we compile the webpack code in the browser instead of the server's nodejs environment? The advantage of this is that we don't need the server's resources for compilation.

There are different solutions to this problem. For example, codesandbox, which defines a browser-based compilation strategy, can be used to package reacts, vue, etc. in the browser. It can also be easily understood that codeandbox does a browser version of webpack.

But the question is, can we execute webpack in the browser instead of doing a new one? Even implementing some webpack-based libraries?

There is a very early webpack issue discussing it . But this demo is too old to run the latest version of webpack.

I am wondering if we can do a browser environment to simulate running Node.js. Node.js and Chrome is both v8, and many of the Node.js lib code can be executed in Chrome. In addition, I found some cool libraries, such as BrowserFS, memfs, rollup-plugin-node-builtins, etc. These libraries can help us build this environment. But there is a key module, Node.js "module" is not available, we need to modify it from Node.js. Node.js supports cjs and esm, but to simplify the problem, I only develop the cjs module for the time being. Next, combine all the modules and try to run the simplest Node.js demo.
After trying a different approach, I successfully ran webpack4 in the browser ! To be precise, you can run use nodebowl to run Node.js library in your browser.
<script src="../../dist/nodebowl.js"></script>
<script>
  const { fs, run } = window.nodebowl;
  fs.writeFileSync('/foo.js', `
    module.exports = 1;
  `);
  fs.writeFileSync('/index.js', `
    const num = require('./foo');
    alert(num);
  `);
  run('/index.js');
</script>
Webpack: https://nodebowl.com/static/examples/webpack.html In this example, the browser will download a webpack node_modules and then run webpack' compiler in the browser.
<script src="../../dist/nodebowl.js"></script>

<h1 id="loading">install webpack node_modules... please wait...</h1>
<button onclick="compile()" id="compile" style="display: none;">click, compile webpack</button>
<div>
  <p>/app/src/index.js</p>
  <textarea id="index" style="width: 600px;height: 100px;">
import foo from './foo';
console.log(foo);
  </textarea>
</div>

<div>
  <p>/app/src/foo.js</p>
  <textarea id="foo" style="width: 600px;height: 100px;">
import foo from './foo';
console.log(foo);
  </textarea>
</div>

<div>
  <p>/app/webpack.js</p>
  <textarea id="webpack" style="width: 600px;height: 100px;">
const path = require('path');
const fs = require('fs');
const webpack = require('webpack');

webpack({
  mode: 'development',
  entry: path.join(__dirname, 'src', 'index.js'),
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },
}, (err, stats) => {

  if (err || stats.hasErrors()) {
    console.log('error');
    return;
  }

  console.log('success');

  const bundlePath = path.join(__dirname, 'dist', 'bundle.js');
  const data = fs.readFileSync(bundlePath, 'utf8');
  document.getElementById('bundle').value = data;
  
});
  </textarea>
</div>

<div>
    <p>/app/dist/bundle.js</p>
    <textarea id="bundle" style="width: 600px;height: 100px;"></textarea>
  </div>

<script>
  const { fs, run, helpers } = nodebowl;
  /*
    -- app
    ----- src
    -------- index.js
    -------- foo.js
    ----- webpack.js
    ----- node_modules
  */
  fs.mkdirSync('/app');
  fs.mkdirSync('/app/src');
  // install node_modules
  helpers.installFromZip('node_modules.zip').then(() => {
    document.getElementById('loading').style.display = 'none';
    document.getElementById('compile').style.display = 'block';
  });
  function compile() {
    fs.writeFileSync('/app/src/index.js', document.getElementById('index').value);
    fs.writeFileSync('/app/src/foo.js', document.getElementById('foo').value);
    fs.writeFileSync('/app/webpack.js', document.getElementById('webpack').value);
    
    run('/app/webpack.js');
  }
</script>
You can also visit https://github.com/nodebowl/nodebowl to see more code and examples.

Tags

Topics of interest