Giter Site home page Giter Site logo

osdevisnot / klap Goto Github PK

View Code? Open in Web Editor NEW
183.0 5.0 4.0 2.32 MB

zero config, zero dependency bundler for tiny javascript packages

Home Page: https://npm.im/klap

License: MIT License

JavaScript 99.17% Shell 0.83%
bundle module-bundler build microlib rollup tiny-modules umd esm esmodules typescript

klap's Introduction

klap ๐Ÿ‘

a zero config, zero dependency bundler for tiny javascript packages.

Build Status David David npm NPM All Contributors

klap output

โœจ Features

  • ๐ŸŽ‰ zero config: bundle your library using only a package.json
  • ๐Ÿ’ฅ zero config: typescript support (just rename *.js to *.ts)
  • ๐ŸŒŸ zero config: code transforms using babel macros
  • ๐ŸŒˆ zero config: code generation using babel plugin codegen
  • ๐Ÿš€ zero dependency: uses gcc-style bundling.
  • ๐Ÿ™ creates tiny bundles for multiple output formats cjs, esm and umd
  • ๐Ÿ”ฅ Modern JS syntax with class properties, async/await, and generators
  • โšก Built in Minification and Gzip Size Tracking
  • ๐ŸŒ€ Built in development server for quick prototyping.
  • ๐ŸŽŠ Supports react, styled-components and emotion out of the box.

๐Ÿ’ช Powered By

  • rollup - Next-generation ES module bundler
  • babel - The compiler for next generation JavaScript
  • typescript - Typed JavaScript at Any Scale.

๐Ÿฝ๏ธ Usage

First, initialize your project using klap init:

npx klap init

Prefer Typescript ? initialize using ts argument:

npx klap init ts

Want to use JSX with Typescript? init using tsx argument:

npx klap init tsx

The init command will create a minimal package.json with source, main, module and browser entries and the build, watch and start scripts.

{
  "name": "...",
  "version": "0.0.0",
  "files": [ "dist" ],
  "source": "src/sum.js",         # source file of your package
  "main": "dist/sum.cjs.js",      # commonjs bundle target
  "module": "dist/sum.esm.js",    # esm bundle target
  "browser": "dist/sum.js",       # umd bundle target
  "scripts": {
    "build": "klap build",        # bundle your package
    "watch": "klap watch",        # bundle your package and watch for changes
    "start": "klap start",        # start a development server
  },
  "devDependencies": {
    "klap": "3.2.0"               # klap as dev dependency
  }
}

Note: Dropping pkg.main will disable cjs output, also applies to esm and umd outputs.

Then use npm run or yarn to invoke npm scripts as you normally would.

See examples for common use cases using klap.

๐Ÿ’ข Granular Control

klap uses sensible defaults for most part. However, as needed, use below properties in package.json to fine tune klap. You can also use cli flags to control config options for klap.

option cli flag(s) description default
source -sย --source source file to compile and bundle src/index.js
cjs -cย --cjs the output file for common js format pkg.main
esm -eย --esm the output file for esm format pkg.module
umd -uย --umd the output file for umd format pkg.browser
types -tย --types the output file for type definitions pkg.types
browserslist -bย --browserslist browserslist compatible compilation target last 2 versions modern browsers if usage is greater than 1%
klap.name -nย --name package name for umd bundles sanitized pkg.name
klap.port -pย --port port for development server 1234
klap.example --example location of index js/ts file for start command public/index.js or pkg.source
klap.fallback --fallback location of index html file for start command public/index.html
klap.target --target target for development server (umd, es) es
klap.sourcemap --no-sourcemap sourcemaps for builds true
klap.minify --no-minify minification for builds true
klap.runtime --runtime the runtime for new JSX transform react
klap.pragma --pragma the JSX Pragma for classic runtime react
klap.pragmaFrag --pragmaFrag JSX Fragment pragma react
klap.usets --usets use typescript compiler for the project false
klap.globals global names for umd bundles {}

--usets allows the library code to use typescript features not supported by @babel/preset-typescript. See const-enums example to enable usage of const enums.

๐Ÿฅ‚ License

klap is licensed under the MIT License.

Documentation is licensed under Creative Common License.

Created with โค๏ธ by @osdevisnot and all contributors.

โœจ Contributors

Thanks goes to these wonderful people (emoji key):


v 1 r t l

๐Ÿ’ป

Daniel Berner

๐Ÿ’ป

Tom Julius

๐Ÿ’ป

Marcus Lindblom

๐Ÿ’ป

This project follows the all-contributors specification. Contributions of any kind welcome!

๐Ÿ’ Supporters

klap's People

Contributors

allcontributors[bot] avatar dependabot-preview[bot] avatar dependabot[bot] avatar osdevisnot avatar tom-julux avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

klap's Issues

Support Dev Expressions

babel-plugin-dev-expression helps eliminate development checks in production mode.

For example:

if (__DEV__) {
  console.log('foo');
}

is transformed to

if (process.env.NODE_ENV !== 'production') {
  console.log('foo');
}

klap already uses @rollup/plugin-replace to treeshake the transformed code.

Klap can't find typescript on init

Howdy! I'm trying to get going with Klap, but upon making a new, empty directory (mkdir klap) and trying to run the typescript init (or even the non-typescript init) I get this error.

๐ŸŒŠ /JS/klap $ npx klap init
internal/modules/cjs/loader.js:883
  throw err;
  ^

Error: Cannot find module 'typescript'
Require stack:
- /home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/dist/index.js
- /home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/cli.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.975034 (/home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/dist/index.js:723369:18)
    at __webpack_require__ (/home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/dist/index.js:723418:43)
    at Object.956237 (/home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/dist/index.js:607953:17)
    at __webpack_require__ (/home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/dist/index.js:723418:43)
    at Module.600669 (/home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/dist/index.js:694661:30)
    at __webpack_require__ (/home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/dist/index.js:723418:43) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/dist/index.js',
    '/home/splash/.nvm/versions/node/v14.15.4/lib/node_modules/klap/cli.js'
  ]
}

Any advice to get this fixed?

Custom babel config

I'd like to make my bundle smaller by passing loose: true to @babel/preset-env but it seems like there's no way to do this.

I think it would be cool to support babel config out of the box

Strange import behaviour on importing external dependency

I'm using klap 5.0.0 and I try to build a file that imports idb from unpkg.

This is the script I'm using.

import { openDB } from 'https://unpkg.com/idb/with-async-ittr?module';

const dbPromise = openDB('wieldy', 1, {
  upgrade(db) {
    const userStore = db.createObjectStore('users', {
      keyPath: 'id',
    });    
  },
});

export const db = {
  async setAll(key, users) {
    const tx = (await dbPromise).transaction(key, 'readwrite')
    const store = tx.objectStore(key)

    for await (const user of users) {
      store.put({ ...user })
    }

    await tx.done;

    this.processCallbacks();
  }
};

This is my package.json.

{
  "name": "idb-import",
  "version": "1.0.0",
  "description": "",
  "source": "index.js",
  "module": "index.esm.js",
  "scripts": {
    "build": "npx klap build",
    "watch": "npx klap watch"
  },
  "devDependencies": {
    "klap": "^5.0.0"
  }
}

This is the output from klap:

[email protected] - Working on build...
'babel-plugin-transform-async-to-promises/helpers' is imported by index.js, but could not be resolved โ€“ treating it as an external dependency
'https://unpkg.com/idb/with-async-ittr?module' is imported by index.js, but could not be resolved โ€“ treating it as an external dependency
        368 B   index.esm.js

The strange part here is that klap includes babel-plugin-transform-async-to-promises/helpers like this.

import{_forAwaitOf as r}from"babel-plugin-transform-async-to-promises/helpers";

And that will not work in the browser.

I don't why but klap includes babel-plugin-transform-async-to-promises/helpers when I include this in my script

for await (const user of users) {
    store.put({ ...user })
}

Unhandled child_process exception: init.js

Line 11 throws an exception if .gitconfig has no github.username field, therefore line 12 never runs (or the rest of the program for that matter).

klap/src/init.js

Lines 10 to 15 in 2e9cc51

const gitInfo = () => {
let user = exec('git config github.username');
if (!user) user = exec('git config user.name');
let email = exec('git config user.email');
return { user, email };
};

Programmable API

Would be great to havea programmable API to use Klap for SSR apps.

something like this would be great:

import { App } from '@tinyhttp/app'
import { Bundler } from 'klap'

const isProd = process.env.NODE_ENV === 'production'

const app = new App()

const bundler = new Bundler({ source: 'index.html', dev: !isProd  })

app.use(bundler.middleware)

if (!isProd) {
  app.get('*', async (req, res) => {
    await bundler.bundle()
   
    res.sendFile('index.html')
 })
}

// ...

Bundle async function expression used as an IIFE

I have this async function expression in my index.js

(async () => {

  const store = await createStore({ actions, mutations, initalState });

  store.subscribe(() => {
    console.log(store.state.message);
  });

})();

Klap throws an error like this: Error: 'return' outside of function.

This is my config:

{
  "name": "minimal",
  "version": "0.0.0",
  "private": true,
  "module": "dist/index.esm.js",
  "source": "src/web/wwwroot/js/index.js",
  "scripts": {
    "build": "klap build"
  },
  "devDependencies": {
    "klap": "^4.2.3"
  }
}

Is it possible to fix?

Bundle and minify es6 modules breaks the named exports

I try to use klap to bundle and minify some vanilla js es modules but it breaks named export/imports. So when I try to use a named export that has been processed by Klap I get an error that the bundle does not have a named export with that particular name.

Make prettier config optional

Is there a way to opt out of the prettier config on klap init? Including it seems a bit too opinionated. What if a project is already using XO, or if it uses prettier from within ESLint, or it just prefers a different prettier config?

Unexpected token

Hi,

Great lib! Looks promising. I'm developing a Leaflet plugin and I need to import some library from node_modules for that.

I receive the following error:

SyntaxError: Unexpected token (1434:11) in xxx\core\dist\esm\index-65dcb9fa.js

Line 1434:

    return import(

It looks like klap has issues with the lazy import statement when an a node_module has import(), if I rename it to something else all is fine (but I'm getting runtime errors, obviously).

The imported code is ESM, do you have any idea why klap can't handle this?

Thanks!

Dynamic imports generates error

I use dynamic imports in my code and when I try to use klap i get the following error. Error: You must set "output.dir" instead of "output.file" when generating multiple chunks.

It seems to be an issue with rollup and it can be solved by using this configuration for rollup.

{
    inlineDynamicImports: true,
}

See issue

Enable support for the experimental syntax 'importAssertions'

In my scripts I have import sheet from "./index.css" assert { type: "css" };
How can I enable this in Klap?

This is the error I get

Add @babel/plugin-syntax-import-assertions (https://git.io/JUbkv) to the 'plugins' section of your Babel config to enable parsing.
(node:67497) UnhandledPromiseRejectionWarning: Error: SyntaxError: /Users/marcus/Library/Mobile Documents/com~apple~CloudDocs/Projects/private/wieldy/src/app/wwwroot/scripts/components/save-button/index.js: Support for the experimental syntax 'importAssertions' isn't currently enabled (5:33):

template system for `init` command

init command currently outputs a basic scaffold. We should add atleast few more templates, such as typescript, react component, etc. We might as well be able to use the examples as template.

Have an option to remove index.js from public directory

I want to use Klap as an app bundler, not for a library.

I'm not sure how to properly to do this but I'd like to setup Klap just to write a web app like with Parcel.

So I don't want index.js or any other JS files to be in public, now I get this:

Error: Could not resolve entry module (public/index.js).

Any way to avoid using this?

Bundle external dependency instead of treating it as external

Using this simple example:

import confetti from 'https://cdn.skypack.dev/canvas-confetti';

const celebrate = () => {
    confetti();
}

const hello = () => {
    console.log('Hello, world.'); 
}

export { hello, celebrate }

I have tried to install the package using yarn add canvas-confetti but it's still treated as external when i run npx klap build

Let the user add more Rollup plugins and configure them differently

Hello,

I am trying to use a custom typescript transformer so I can make use of compile-time transformations, but I can't find a way to add it to the build. I haven't tested but I guess it won't read a rollup config file if I create it, right? (ref.: https://github.com/osdevisnot/klap/blob/master/src/plugins.js#L16)

I am happy to send a PR with a reference implementation, but before considering working on it, I would like to know if you have any suggestion of which approach to follow. For example:

  • Create a klap.config.js (or any name) file that supports hooking config changes (like pointcuts/hooks) in some points of the plugin (at least plugins.js file initially); OR
  • Find a way to use the rollup config file to override what's previously configured (Convention over configuration); OR
  • Just implement a basic support to typescript transformers and add it to klap object of package.json

Any other approach or suggestion is welcome :)

Thanks for the awesome project!

Build development environment?

Hi!

I'm developing a library and I would like to publish the development environment as a static site.

Any suggestions?

Thanks!

drop `umd` bundling in favor of `iife`?

We should consider dropping umd bundling in favor of iife. Few points to note:

  • umd overlaps a lot with iife.
  • umd was mainly added for IE11 compat.
  • klap generates separate module formats for node vs modern browsers, which makes umd little pointless.
  • iife should help with IE11 compatibility for most cases.

I am unsure if I am missing anything.

This would mean we change compilation strategy from:

pkg.main generates cjs
pkg.module generates es
pkg.browser generates umd

to

pkg.main generates cjs
pkg.module generates es
pkg.browser generates iife

This would also mean changing the build target for start command to either es or iife

Let's keep this issue open for user feedback.

Cryptic errors when trying to build

When running klap build --pragma=h I get this:

โฏ yarn build
yarn run v1.19.2
warning package.json: No license field
$ klap build --pragma=h
[email protected] - Working on build...
(node:27361) UnhandledPromiseRejectionWarning: Error: Could not resolve entry module (src/money-target.js).
    at error (/home/v1rtl/Coding/money-target/node_modules/klap/dist/index.js:23:268012)
    at /home/v1rtl/Coding/money-target/node_modules/klap/dist/index.js:23:400303
    at async Promise.all (index 0)
    at async Promise.all (index 0)
    at async Promise.all (index 0)

no error message at all, so I can't figure out what's wrong.

here's the thing I try to build:

import { h, render } from 'preact'

/** @jsx h */

render(<h1>Hello World</h1>, document.getElementById('app'))

I know that the error is that I didn't name the file properly but it should output this error in a more friendly way

Question: ncc vs rollup

@osdevisnot

I'm curious about the choice to use ncc vs Rollup to compile klap. What are the differences/advantages? Do you have any idea about how they compare in terms of tree-shaking?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.