tacker

a simple web bundler
git clone https://tongong.net/git/tacker.git
Log | Files | Refs | README

README.md (5056B)


      1 # tacker
      2 
      3 `tacker` takes your files and staples them together. The goal of this project
      4 is to be a simple web bundler independent of the disaster that is the modern
      5 npm ecosystem. The main use case of `tacker` is bundling single page
      6 applications into a single `.html` file for easier distribution. You can of
      7 course also use it to quickly get access to modularity when developing
      8 userscripts, to inline images into your static page, etc.
      9 
     10 Advanced bundling and optimization techniques are not in scope
     11 of `tacker` - try one of the bloated mainstream bundlers instead:
     12 - webpack (75 dependencies)
     13 - parcel (184 dependencies)
     14 - browserify (175 dependencies)
     15 - ...
     16 
     17 `tacker` was written as an experimental project in the new
     18 [hare programming language](https://harelang.org/).
     19 
     20 ## features
     21 - entrypoints:
     22   - HTML
     23     - `<script src="...">` tags
     24     - `<link rel="stylesheet" href="...">` tags
     25     - binary data as base64 (`<audio>`, `<embed>`, `<img>`, `<source>`,
     26       `<track>`, `<video>`)
     27   - CSS
     28     - other style sheets (`@import url(...)`)
     29     - binary data as base64 (e.g. `background-image: url(...)`)
     30   - JS
     31     - a subset of CommonJS modules (see below for important drawbacks)
     32       - `require(...)`
     33       - `module.exports` and `exports`
     34 
     35 The "conceptual module name space root" is the working directory. This means
     36 that required paths which are not relative are resolved from the cwd. For
     37 security reasons only files in the cwd can be bundled. This can be changed with
     38 the `-p` option. Input and output file name stay relative to the cwd. The
     39 `.js` in `require()` imports is optional.
     40 
     41 `tacker` does not aim to be 100% spec-compliant. The goal is to work in all
     42 common scenarios without laying to much emphasis on obscure edge cases. It is a
     43 tacker after all - not an industrial robot. Though unlike a real-world tacker
     44 your security should not be at hazard. Malicious source files can obviously
     45 take over your bundled page but they can never take over your system.
     46 
     47 ## known bugs & missing features
     48 
     49 ### require()
     50 CommonJS was chosen out of personal preference and its simplicity compared to
     51 ES Modules (tree-shaking optimizations enabled by ES Modules would not be
     52 implemented either way). The parser is rather simple though. To confirm to the
     53 CommonJS spec arbitrary javascript expressions (as the argument to `require()`)
     54 would need to be able to be evaluated at bundle-time. As `require` is just a
     55 value and not special syntax the same is the case for the whole program as
     56 every function could be possibly rebound to `require`. This requires the
     57 complete execution of the program at bundle-time to be able to reason about
     58 possible aliases to `require`. This is impossible and thus `require()` will be
     59 treated as special syntax. This implementation (and in fact every CommonJS
     60 bundler) is thus wrong but should work for every sane usage of `require()`.
     61 
     62 The `require()` macro expects a string literal with single or double quotes as
     63 single argument. Whitespace between `(` and `"`/`'`  or between `"`/`'` and `)`
     64 is forbidden. Currently no escape sequences are allowed as this would add a lot
     65 of complexity and is not needed for sane file names. This feature may be added
     66 in the future.
     67 
     68 Correctly expanding the `require()` macro requires recognizing string
     69 literals (to not cause bugs by changing string content). This in turn requires
     70 correctly recognizing regex literals as they could contain quote characters and
     71 as far as I know this requires parsing the whole AST (how to decide if `/5/` is
     72 a regex or part of an arithmetic expression?). A similar problem arises for
     73 template literals. To avoid this complexity `tacker` only reads until reaching
     74 the first character that could be start of a string, regex or template literal.
     75 This means that module imports have to be at the top of each source file which
     76 is the case already for most projects. All potentially skipped `require()`
     77 calls will be announced as a warning.
     78 
     79 ### script end tags & regex literals
     80 When inlining javascript in html, the script cannot contain script end tags
     81 (`</script>`). To handle this all occurrences of `</script` will be replaced by
     82 `<\/script`. This works in string literals and comments and should never occur
     83 in normal code. I am however not sure about regex literals - there could be
     84 very rare edge cases where these break.
     85 
     86 ### external resources
     87 Bundling of external scripts, images, etc. is currently forbidden and `tacker`
     88 will throw an error. There are two alternative behaviors:
     89 
     90 1. Bundling the external resource: I think it is a bad idea to bundle random
     91    assets from the internet.
     92 2. Allowing references to external resources without bundling them: This would
     93    be a better way of handling external resources but it creates a runtime
     94    dependency which is not very sustainable considering link rot.
     95 
     96 It would be possible to enable behavior (2) via a command argument flag but I
     97 currently do not see the point in implementing this feature.
     98 
     99 ## todo
    100 - css bundling
    101 - larger test coverage
    102 - online mode to bundle third party scripts or css