ts-webpack-builder
An npm package used to build other npm packages or via TypeScript and webpack.
Note: This project is not intended for use by anyone other than the creator.
npm install --save-dev @messman/ts-webpack-builder
Why?
Why use webpack to create libraries? You could just use a tsconfig.json
file and be done with it. But the problems with that include:
- You can't have a single output JS file unless you are using
AMD
orSystem
as themodule
property. Webpack allows us to create a single JS output (although we can't have a single output TypeScript declaration file - more on that below). - You don't get optimization, tree-shaking, etc.
- You can't run other plugins, like
babel
.
Thus, this package was born. It's like many others, but I wanted to create one myself. If you want a package that's going to be better supported or more powerful, check out ts-engine.
Features
- Can run for both client (web) and server (node) libraries. (They require different bundling strategies.)
- Hides webpack config for libraries behind-the-scenes so it doesn't have to be added to every project.
- Optionally can run the code through babel (and also hides it behind the scenes so it doesn't have to be added to every project). (This hasn't been well-tested.)
- Includes a
watch
setting. - Can be imported and run from code or run through a CLI for direct builds from
package.json
. - Creates UMD libraries.
Build
Build with npm start
. That runs the webpack build (meta, right) to create this library, then runs the tsc
command to build the cli.
Use
To use in a project, you can install (dev) or use npm link
:
- In the root of this downloaded source, run
npm link
. That installs this package in the npm global space for this machine. - In the project you want to use, run
npm link @messman/ts-webpack-builder
. That finds the global installation and binds it into that project. Note, thets-webpack-builder
won't show up in thepackage.json
dependencies. That's just not hownpm link
works. But it will show up innode_modules
(symlink).
Once this tool is added to the consuming project, you can either create a script in that project to call into this tool (like a runner.js
) or you can use the CLI.
See the test
folder for more information on both. The CLI should be improved in the future to be more customizable / have better shortcuts.
In your package.json, to create a usable library:
"main": "dist/index.js",
"types": "dist/index.d.ts",
projects that consume the output of your target project may need their tsconfig.json
changed to
"moduleResolution": "Node"
In order to resolve packages in the node_modules
directory when using module imports.
CLI
The CLI exists in the cli
folder. It is built separately from the rest of the code in src
and is actually bound to the built code in dist
folder (so that it only uses the types and doesn't try to transpile anything in src
- that's also why it doesn't get put into dist
after transpilation).
When installed in the target project, the CLI is accessible at ./node_modules/.bin/@messman/ts-webpack-builder
. You can run it like that or call npx ts-webpack-builder
. Or you can set up a custom command through package.json
:
{
"scripts": {
"start-cli": "ts-webpack-builder",
},
}
You can pass in any arguments there as well.
Notes on the CLI:
- The CLI does not require you to pass in an
absoluteRoot
property. - There is a CLI options to specify a path to a babel config file.
- The CLI will automatically look for a file in your project called
tswb.js
that can contain build options. This file can specify one object of build options or a dictionary.
See the test area for examples.
Development
Typical steps are:
- Make a change, save, then call
npm start
in the root of this project to do the webpack build and the CLI build. -
cd ../test
to go into the test. - Run the tests (see the
test
README)
There are some times where you may need to delete the ts-webpack-builder
folder in node_modules
in test
, then re-link, like after you've installed something new.
This project uses a common tsconfig.json
.
Future tasks:
- Add a test for babel config.
Babel
Use of babel is not tested. It probably doesn't work yet. The idea is as such:
- If using a script file to run the build, you can pass the babel config through
babelConfig
as an object. - Through the CLI, you can provide the path to a babel config (which could be a JS or JSON file).
In both cases, you need to install your presets as dev dependencies in the consuming project - ts-webpack-builder
does not have any.
TypeScript Declaration Files
Every time I create a library, I question why I can't bundle TypeScript Definition files like I bundle JavaScript files. Answer: because it's a huge hassle and not worth the time.
See TypeScript #4433
Many hours have been spent researching the possibilities of combining declaration files into a single output. Long story short, it's not possible unless you:
- do it yourself (like those that write their own definitions for
@types
) - create a very specialized build library to handle it
- use one of the solutions out there (like
dts-bundle-generator
) that comes with caveats
Why's it so difficult? When webpack combines into a single output file, it's because it's essentially wrapping the entire JS module environment. That's just not possible with declarations, which are more static. So the problems you run into include, for example, you wouldn't be able to name any types the same, because they will be flattened and override each other. Then on top of that, you wouldn't be able to handle the .map
files that allow you to go directly to the source!
History
- 2.0.0: Upgrade to Webpack v5