A local installation in the project is usually more desirable for pinning and synchronizing the instapack version used by the CI and the development team.
Ensure package.json exists in the project folder. (If not, run npm init -y)
Open command prompt in that folder to install instapack locally: npm install instapack -D -E
Zero Configurations: Hyper-opinionated front-end project build system. It just works! :sparkling_heart:
Beginner-friendly: Lower the barrier of entry for developing a modern web app. :balloon:
Unify and standardize team build system across multiple projects, for any JS frameworks. :fist:
Built-in new project scaffold tool for assorted JS frameworks. :gift:
Improve source code quality and maintainability with type hints, recommended lints, and compile-time checks. :eyeglasses:
Rich debugging experience: set breakpoints, view variables, and step into the TypeScript source code! :mag:
Introduce structures to the front-end source code using standard module systems. :bento:
Enforce best practices when building apps, which may significantly impact page load time. :hammer_and_wrench: (i.e. tree-shaking, code-splitting, bundling, and minification)
Blur the boundary between design-time and coding-time using lightning-fast serve or watch + dev build mode. :zap:
But... Why?
instapack is a first-class end-to-end TypeScript and Sass build tool. :tophat: Meaning, it comes with an assurance to compile projects written using standard TypeScript or Sass successfully regardless of frameworks used. :rainbow: This mindset is the differentiating factor between instapack and other CLI tools, which tend to be designed framework-first but TypeScript-second!
instapack is battle-tested :hocho: and is designed to cover most normal use cases when developing a modern web app. Powered by webpack, instapack readily consumes modern JS modules (ES, CommonJS, UMD) and more (plain HTML templates, Vue SFC, TypeScript JSX).
With this powerful tool, you can save time :watch:, save precious SSD space :space_invader:, and save yourself from the pain of maintaining project build scripts! :coffee:
Commands
You may use instapack or ipack to invoke the command line interface.
new [template]
Scaffolds a new instapack project into current working directory. All templates target ES2015, compatible with modern major browsers unless noted otherwise. These templates are available:
angularjs for developing a legacy web app targeting ES5 browsers (Internet Explorer 10+) using AngularJS 1.7 and Bootstrap 3. Also includes jquery-validation-unobtrusive for ASP.NET MVC client-side validation. DO NOT USE THIS TEMPLATE!
If no template parameter is provided, react will be chosen. :atom_symbol:
build [project]
Performs compilation of selected project type. Available projects: all, js, css and copy. If no project parameter is provided, all will be chosen.
In addition, build flags are available:
--watch or -w enables automatic incremental build on source code changes. :robot:
--dev or -d disables build outputs optimization and minification for FAST build! :fire:
--serve or -s enables Hot Reload development mode using dedicated build server. :recycle: Read more β
--https can be used with --serve flag, allowing the Hot Reload dev server to use https:// protocol.
This feature requires mkcert third-party utility to be installed and available on the CLI path.
--experimental-react-refresh or -R enables dev server with React Fast Refresh (new native Hot Reload).
--stats generates stats.json next to the TypeScript build outputs, which can be analyzed by a third-party tool: webpack-bundle-analyzer. This flag will be ignored during watch mode.
--cow allows overwriting files in output folder by copy assets build tool.
Multiple build flags can be combined, for example: ipack -dw = dev + watch mode
set
package-manager allows setting default package manager to be used for restoring and integrity-checking node_modules prior build. Possible values: npm, pnpm, yarn, disabled (default: npm)
The yarn setting refers to the legacy Yarn 1.
mute disables voice assistant on build fails during watch mode when set to true. Possible values: true and false (default: false)
Configurations
instapack puts configurations inside package.json to reduce project files clutter. For example, this is the included package.json with vue template:
name, version, private, and dependencies fields were removed for brevity.
input allows setting the input folder path. By default, it is set to client
output allows setting the output folder path. By default, it is set to wwwroot
jsOut allows setting the JS output file name. By default, it is set to ipack.js
cssOut allows setting the CSS output file name. By default, it is set to ipack.css
namespace allows exposing modules exported via JS entry point (index.ts) to be accessed as an object in the browser window global object.
For example: namespace: "instapack" enables accessing export function foo() as window.instapack.foo() (which then can be invoked via Blazor JS Interop: await JsRuntime.InvokeAsync<string>("instapack.foo");)
umdLibraryProject can be set to true to allow building a single-entry-point (without .dll.js file) UMD JS bundle. Use this option when developing a library package! (e.g. npm or Razor Class Library)
Use namespace option to name your UMD module. Not setting namespace option will result in the assignment of all properties returned by the entry point be assigned directly to the root object.
alias allows overriding module import calls from all files, including dependencies. Read more β
externals allows rewriting module import calls from all files, including dependencies, to globally exposed objects via window object. Read more β
This technique enables usage of scripts hosted on CDN such as unpkg!
This technique also allows referencing non-module, old-school IIFE JS loaded via <script> which provides excellent interop with older libraries!
Example:
{
"instapack": {
"externals": {
"jquery": "
quot;
}
}
}
// converts this...
import jQuery from 'jquery';
// into something similar to this...
// const jQuery = window["quot;];
// allowing CDN to be used instead of bundling the library:
// <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
copy allows copying static assets from the npm folder (node_modules) into the project output folder (e.g. wwwroot) during build.
library accepts a package name. The package MUST be installed in the project package.json and cannot be transient implicit / merely a sub-dependency of other packages.
files accepts a list of file names OR folder names OR glob patterns.
destination accepts a sub-folder path inside the project output directory.
The copy output preserves the folder structure of the origin folders up to the topmost common directory path. (For example, copying node_modules/library/a/b/c.txt and node_modules/library/a/d/f.txt will result in wwwroot/destination/b/c.txt and wwwroot/destination/d/f.txt to be created)
Example:
Copy all files inside node_modules/@fortawesome/fontawesome-free/webfonts folder, except files in that folder prefixed with fa-brands into project output sub-folder wwwroot/webfonts
port1 can be set for declaring a static port number to be used by the Hot Reload server. If not set or is already used, the port number will be randomized. Read more β
Babel Integration
instapack supports .babelrc in the project root folder. Babel transformations will be applied AFTER TypeScript compilation.
ESLint Integration
instapack 8 supports ESLint 7 configuration, applied directly in-memory to TypeScript source code during type-check.
Source code will be linted only when it can be compiled correctly.
Here is an example .eslintrc.json placed in the project root (next to tsconfig.json). eslint and typescript-eslint packages are required to be installed in the project:
Out of the box, instapack lints <script lang="ts"></script> in Vue Single-File Components without any special ESLint configuration for Vue.js! :heavy_check_mark:
However, these lint errors will not be visible in Visual Studio Code... To remedy this issue, add these packages to the project and use the following special ESLint configuration instead:
Hot Reload development mode allows a developer to update application code while preserving runtime states, without triggering browser refresh when not needed.
instapack supports Hot Reload for popular JS frameworks by using --serve or -s flags, which also enables watch and dev modes automatically.
Vue.js
Hot Reload for Vue.js projects using Single-File Component format (.vue) has been enabled out of the box.
No further configurations necessary! :tada:
React
When using --experimental-react-refresh build flag, Fast Refresh (Hot Reload) for React projects has been enabled out of the box without requiring any code changes!
If not using Fast Refresh, use react-hot-loader package and configure the project manually, following the instructions provided.
Module Systems
TypeScript / ES Modules
Imports and exports other .ts / .tsx files in the project or normal JS modules from node_modules. This technique allows the ease of development using intellisense for modules with type definitions:
The module has types or typings field pointing to TypeScript declaration files (*.d.ts) in its package.json. For example: vue, linq
The module has @types installed. For example, react and @types/react
import List from 'linq';
When the imported module does not have any type definitions, it will be imported as any data type (no intellisense).
ES Modules: Dynamic Import
instapack supports code-splitting using ESM dynamic import() syntax to load on-demand modules automatically, greatly reducing the initial page load on large application:
Vue.component(
'my-component',
// The `import` function returns a Promise<T>
() => import('./MyComponent.vue')
)
An excerpt of build log when using dynamic import:
To use this syntax within TypeScript, module compiler option in tsconfig.json must be set to esnext
CommonJS / Node.js require
Imports Node.js modules within the project or from node_modules. However, you WILL NOT get intellisense! (Modules will be imported as any data type.)
const $ = require('jquery');
CommonJS require method in TypeScript is provided through @types/requirejs or @types/node packages.
HTML Modules
Imports an .html file to be minified and stringified. This technique is invaluable for working with frameworks relying on HTML-based templates such as AngularJS:
Basic CSS in <style> (or <style scoped> or <style module>) code blocks should work, but Sass CANNOT be used and the resulting CSS will NOT be auto-prefixed and minified. You are advised to write CSS using the instapack Sass project instead!
When using Visual Studio Code, install Vetur extension to get syntax highlighting and TypeScript intellisense.
Vue 3: Single-File Components
instapack 8.0.0 can compile Vue 3 components too! Below example showcases a Vue 3 component written using the brand new Composition API.
HEADS UP! The Sass team discourages the continued use of the @import rule. Sass will gradually phase it out over the next few years, and eventually remove it from the language entirely. Prefer the @use rule instead.
These options allow unusual module imports using non-relative paths:
import { x } from 'stuff'; // might resolve to /client/js/lib/stuff/index.ts
import { y } from 'stuff/y'; // might resolve to /client/js/lib/stuff/y.ts
import { xyz } from 'abc/def'; // might resolve to /client/js/abc/def.ts or /client/js/globals/abc/def.ts
instapack will also not resolve symlinks if TypeScript compiler option preserveSymlinks is set to true
Bug reports will be dealt promptly. Periodic maintenance will be also done by updating dependencies version. These actions will increment the patch version.
New non-breaking features will increment the minor version. Breaking changes will increment the major version. View breaking changes here.
Occasionally, beta builds will be published (instapack@beta) for showcasing the bleeding edge version of the tool.
Alternatively, you may build directly from the source code repository:
git clone https://github.com/ryanelian/instapack.git
cd instapack
./link.ps1
./build.ps1
ipack --version
FAQ
Can I use [insert_framework_name_here] ?
Yes, absolutely!
If it worked when using normal JS, it WILL work with instapack. (Other frameworks not shipped in new project templates such as Angular 2+, Preact, Inferno.js, Mithril.js are known to be working with instapack.)
Add the packages required for your project and then start hacking. We'll take care of the outputs.
If there are newer major frameworks requiring custom file compilation (like .vue) AND it happened to support TypeScript, please create an issue to allow instapack to be modified to support such formats.
Is it even safe to target ES2015?
As of June 2017, all major browsers (except Internet Explorer) supports ES2015. iOS 10.3 and above supports ES2015.
This is a sample Dockerfile build recipe for building ASP.NET Core + instapack project:
This recipe assumes that the project Dockerfile is located in the root / solution folder (next to /MyApp.sln), with the ASP.NET Core + instapack project located in /MyApp (/MyApp/MyApp.csproj and /MyApp/package.json)
FROM node:12-slim AS instapack
# using pnpm is faster (optional)
RUN npm install -g pnpm
RUN pnpm install -g instapack
COPY . /src
WORKDIR /src/MyApp
RUN ipack
FROM mcr.microsoft.com/dotnet/sdk:5.0 as build
COPY --from=instapack /src /src
WORKDIR /src/MyApp
RUN dotnet restore
RUN dotnet publish -c Release
FROM mcr.microsoft.com/dotnet/aspnet:5.0 as runtime
COPY --from=build /src/MyApp/bin/Release/net5.0/publish /app
WORKDIR /app
ENTRYPOINT ["dotnet", "MyApp.dll"]
Build locally using Linux container: docker build --pull --tag myapp:0.0.1 .
Run app via command: docker run -p 12345:80 myapp:0.0.1
When developing multiple front-end projects in one solution, simply run instapack multiple times in different WORKDIR
How to build instapack projects on GitLab?
Place .gitlab-ci.yml next to the Dockerfile to automatically build the image remotely on-commit, then push the image to the GitLab registry:
Can I change the index.ts / index.scss entry point?
Nope.
Can I change the js / css output sub-folder name?
Nope.
Can I build multiple entry points?
Nope.
However, you can eject the client folder out of the back-end project folder, rename the jsOut file, and then redirect the output folder path back into the assets folder of the back-end project:
Add anti-virus exclusion to Git installation folder: C:\Program Files\Git. To double check, type: where.exe git
Use very short root folder name for projects, such as D:\VS, to avoid potential problems with Windows system paths over 260 characters long. Then exclude the folder from the anti-virus.