How can Babel be used without bundler, but with a dev-experience similar to webpack?
Asked Answered
K

4

10

I'm trying to build a new project with ES6 modules without bundling. I still want to use babel-7 to translate TypeScript and JSX to JS. I find it hard to figure out how to set up a development-server for it. I couldn't find any kind of "babel-dev-server" that works similar to webpack-dev-server (hot-module-reloading, browser-sync, file-watcher).

One possibility would be to use browser sync as a static server on e.g. dist and run something like babel src --out-dir dist --watch in parallel. But this excludes hot-reloading and seems a bit clumsy to me. Besides, it would still be useful for build- and dev-steps if you could give the JS-files a hash to control caching better. Or can I configure a build-tool like webpack so that it doesn't perform bundling but still performs some transformations (like putting the hashs in the filenames in imports)?

Kairouan answered 14/10, 2018 at 18:27 Comment(3)
What is your end goal? Why do you want to avoid using webpack-dev-server? If you want hot-module-reloading, etc., then that would be a good tool to use.Thermoluminescence
Would sourcemap solve you problem? it enables you to see separate files on browser.Sancha
@ToddChaffee I believe that due to HTTP/2 and the native browser support of import/export, bundling is neither optimal nor needed. It changes the code so much that you don't know exactly how it works and complicates the development process (e.g. I find webpack and the principle of bundling really hard to understand or explain to a beginner). That's why I wanted to try how to live without webpack, or at least without a "magic" bundling process.Kairouan
K
1

With the latest release of Snowpack (formerly @pika/web) this should be possible now!

From their website:

TL;DR - With Snowpack you can build modern web apps (using React, Vue, etc.) without a bundler (like Webpack, Parcel, Rollup). No more waiting for your bundler to rebuild your site every time you hit save. Instead, every change is reflected in the browser instantly.

And their "How it Works":

  1. Instead of bundling on every change, just run Snowpack once right after npm install.
  2. Snowpack re-installs your dependencies as single JS files to a new web_modules/ directory. It never touches your source code.
  3. Write code, import those dependencies via an ESM import, and then run it all in the browser.
  4. Skip the bundle step and see your changes reflected in the browser immediately after hitting save.
  5. Keep using your favorite web frameworks and build tools! Babel & TypeScript supported.

check https://www.snowpack.dev/ for more information, they have done a great job with their documentation, it looks really promising!

Kairouan answered 14/1, 2020 at 9:22 Comment(0)
S
1

Prototyping way

A very simple way to do this is to see the server and the transpiling as separate steps

You could use a standalone version of babel as the first script that you load, so you can write jsx inside your html document of javascript files without compiling them.

Simply add on of the cdn links from https://cdnjs.com/libraries/babel-standalone/ as a script like so:

<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.0.0-beta.3/babel.min.js"></script>
    <script src="/your/jsx/here.js"></script>
    <script>
      // or here
    </script>
  </head>
  <body>
    <div id="application" />
    <noscript>This app needs javascript enabled in order to run.</noscript>
  </body>
</html>

This would allow you to really quickly prototype things using any webserver that watches files. You can do this using any task runner plugin (i.e. for grunt or gulp) or if you are using visual studio have a look at LiveServer plugin.

When you are moving to production grade you might not want to include the entire babel library. See the other two approaches.

Webpack way

You're asking how to use webpack without bundling. Which can be done using file loader plugin to load every file separately, using a glob pattern. Do make sure whether this is indeed what you need. If all you want is to simply debug your code an relate it back to the original file after compiling, all you need is a standard webpack configuration using bundling and sourcemaps.

Taskrunner way

One way to have even more control over how each file is processed, you can use a taskrunner to do the compile step for you. Below is a simplified example configuration for taskrunner https://gulpjs.com/.

gulpfile.js

const gulp = require('gulp');
const watch = require('gulp-watch');
const webpackStream = require('webpack-stream');
const webpack = require('webpack');
const eslint = require('gulp-eslint');

gulp.task('watch', function() {
  return watch('src/**.js', ['compile']);
});

gulp.task('lint', function() {
  return gulp.src(['src/*.js', 'src/*/*.js'])
    .pipe(eslint({
      parser: 'babel-eslint',
      parserOptions: {
        ecmaFeatures: {
          jsx: true
        },
        sourceType: 'module'
      }
    }))
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('compile', ['lint'], function() {
  return gulp.src('src/main.js')
    .pipe(webpackStream({
      output: {
        filename: 'main.js',
        libraryTarget: 'commonjs2',
        sourceMapFilename: 'main.js.map',
      },
      plugins: [],
      module: {
        loaders: [
          {
            test: /\.js$/,
            loader: 'babel-loader',
            query: {
              presets: [
                require.resolve('babel-preset-es2015'),
                require.resolve('babel-preset-stage-0'),
              ],
            },
          },
        ],
      },
    }), webpack)
    .pipe(gulp.dest('dist/'));
});

This example file can be run, using gulp watch. It'll watch the files for a chance and when it does trigger the other tasks.

I only had an example with webpack, but you can replace it by any other compiler component or even write your own compile step if you want (probably you don't).

This way you have exact control over every step your files go through. Most of which (and more) can also be achieved using the Webpack way. However, it would have the downside of inserting all its boilerplate on top of each processed file, when processing each file as a separate bundle. Ultimately probably something could be done with common chunks plugin.

Scriabin answered 24/10, 2018 at 10:31 Comment(2)
Many thanks for your explanations! Especially in the development cycle I find the approach with @babel/standalone exciting (I would use babel7 ;-) ). I find the other approaches very useful to get the app ready for production. I won't "accept" your answer yet, because I want to test it first (if I can find the time) how to assemble it and if it works as I hope it will.Kairouan
Great, let me know if you're missing something specific in your implementation. Perhaps we can help other people out too.Scriabin
K
1

With the latest release of Snowpack (formerly @pika/web) this should be possible now!

From their website:

TL;DR - With Snowpack you can build modern web apps (using React, Vue, etc.) without a bundler (like Webpack, Parcel, Rollup). No more waiting for your bundler to rebuild your site every time you hit save. Instead, every change is reflected in the browser instantly.

And their "How it Works":

  1. Instead of bundling on every change, just run Snowpack once right after npm install.
  2. Snowpack re-installs your dependencies as single JS files to a new web_modules/ directory. It never touches your source code.
  3. Write code, import those dependencies via an ESM import, and then run it all in the browser.
  4. Skip the bundle step and see your changes reflected in the browser immediately after hitting save.
  5. Keep using your favorite web frameworks and build tools! Babel & TypeScript supported.

check https://www.snowpack.dev/ for more information, they have done a great job with their documentation, it looks really promising!

Kairouan answered 14/1, 2020 at 9:22 Comment(0)
T
0

With webpack and source maps, it shouldn't matter that it changes your code. While this can be a challenge to set up initially, once you get it working you can look at your original source code in the browser debugging tools exactly as they appear to you on disk. The VS Code editor also does a good job of supporting this feature, allowing you to set breakpoints and look at the values of variables directly in your editor without having to use the browser developer tools.

However, if you are still set on trying to get this to work with your original source files then you are right that your ES6 code should just work in most modern browsers

For live reload you could check out the npm livereload package.

Or you could roll your own and figure out how webpack-dev-server does it. They use the chokidar npm package to watch the file system for changes and then they notify the broswer via web sockets. You could probably throw something together that's similar with a little effort.

Here is how webpack-dev-server initiates it:

const watcher = chokidar.watch(watchPath, options);

watcher.on('change', () => {
  this.sockWrite(this.sockets, 'content-changed');
});

Obviously there is some JavaScript that runs in the browser waiting on a websocket for that message.

Thermoluminescence answered 22/10, 2018 at 19:22 Comment(1)
After a short review it seems to become quite complex. You have to implement your own node-server with websocket and then implement the hot-reloading functionality on the client and server side. I still couldn't figure out exactly how this works during my short review. It's definitely a nice exercise to familiarize yourself with node servers, websockets and the HMR principle, but unfortunately I don't have enough free time at the moment. For reference: medium.com/@maheshsenni/… could be a good resource.Kairouan
P
0

You could use a Webpack plugin like Emit All.

Pah answered 23/10, 2018 at 16:58 Comment(2)
That seems nice. Do you have experience with whether it can be integrated with webpack-dev-server?Kairouan
@PutziSan it shouldn't be a problem.Pah

© 2022 - 2024 — McMap. All rights reserved.