Webpack

Webpack

Webpack is JavaScript module bundler. Webpack takes modules with dependencies and generates static assets representing those modules. Webpack's key features are rooted in extensibility and enabling developers to use best-practices in Web Architecture and Web Performance.
Madyson  Moore

Madyson Moore

1668675230

Use Webpack's Url Loader with Example

In this tutorial we learn How to use Webpack's url loader. `url-loader` lets you `import` arbitrary files, like images.

Webpack's url-loader lets you import arbitrary files, like images. If you import a .png file, url-loader will ensure that import resolves to a Base64 string representing the contents of the file.

Example

Here is an example to display a .png file using the url-loader option. The project directory looks like the following:

root
|__deploy
|  |
|  |__index.html
|  |__main.bundle.js
|
|__node_modules
|
|__src
|  |
|  |__app.js
|  |__component.js
|  |__image.js
|
|__package-lock.json
|__package.json
|__webpack.config.js
|__yinyang.png

The dependencies needed are:

  • file-loader
  • html-webpack-plugin
  • url-loader
  • webpack
  • webpack-cli

This is the webpack configuration file:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      title: "Webpack Output",
    }),
  ],
  entry: {
    main: path.resolve(__dirname, "./src/app.js"),
  },
  output: {
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, "deploy"),
  },
  optimization: {
    minimize: false,
  },
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/i,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 8192,
              mimetype: "image/png",
              encoding: true,
            },
          },
        ],
      },
    ],
  },
};

Below are the javascript file contents:

component.js

export default (text = "Hello, Webpack!") => {
  const element = document.createElement("h1");

  element.innerHTML = text;

  return element;
};

image.js

import image from "../image/yinyang.png";

export default () => {
  const element = document.createElement("img");
  element.src = image;

  return element;
};

app.js

import component from "./component";
import image from "./image";

document.body.appendChild(component());
document.body.appendChild(image());

Once you have everything installed and setup properly, run: webpack --mode development to compile and bundle. This will create the deploy folder with the index.html and main.bundle.js file.

This is what the app.js will look like after Webpack bundles it. Notice the const yinyang = "..." code that contains the base64 representation of yinyang.png.

main.bundle.js

/******/ (() => {
  // webpackBootstrap
  /******/ "use strict";
  var __webpack_exports__ = {}; // CONCATENATED MODULE: ./src/component.js

  /* harmony default export */ const component = (text = "Hello, Webpack!") => {
    const element = document.createElement("h1");

    element.innerHTML = text;

    return element;
  }; // CONCATENATED MODULE: ./yinyang.png
  /* harmony default export */ const yinyang =
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAAJYklEQVRoBbVaSWhUTRDuJBo1olGjonHfohIXlIheRBAJuN30kEMQclAEFTx4CaIicTtGPCiIgnrwInoRUVExSERR3Fc0rnEPGpeYTMb0/331Xj06M28m8yb5C2q6X/X2VXV1db9+k2Oyo7ylS5f2OnfuXFtC80I8jwaPAheBC8CkFnATuBH8HtwMdqkPHuLgf64wk3xOJpUS6uTjOebIykaNGlW+fv36RZMnT54xfPjw4pEjR5qBAwea/HxWNeb379/m/fv35ubNm6a2tvbD27dvHw4YMODqggULLly8ePGW01di305R97N51lpVmAOt3bdvX31dXZ399esXijpRHE8xcJvPzFNmf/z4YU+dOmXRXri0tLSefSH1tDWGY+SBe4xyDh061NvprWr//v0NsCjxKBFoKzj2z6OOeDxuXYa4A+X/WId137x507Zy5UpRYurUqUwbevfuXeWMwzHVYI44Wjb3ypUrvfwmJRs3bqxraGjA+EJq5TjA2Y4O4ktPrMO6ZBJmLr5mzRq6YxzuJ8rk5eXV4XmqPybHzvXzkZNcjKEWqDxx4oS4AGS0dhxgSMhmR5wdUlNTk507d24H0MXHjRvHoGBzcnK4oCt9xMQQWQm3Qc2dO3cUZasOrILupNrX7du3xfpjx461WNytVMLnGl8JJi4mR5ycdS1fC18lRpqrPYrF1VU0DVPU7W/Hjh0CesqUKUzbwZwF5mvBpIxmIsfx+RoffAwD0WXCMITK1MfdwjAZy3UWOMsAaYcNG2b79evHPBXg+mBeZ4JrQt0a2QRyok2l7zYErr7v4kmZV0VbWlos+yAzT9Iyt7Eqhr3CLlmyRJQYMmSIpIBHJXQmdE24EbGTBhp7S5wF2+4O1lVewXz69MmuXr1aQUieMpLW0b5cpdSNsDEGbYGQ7sRnKlICJilW74m/6FCmhqHS77zV7VwHTJW6dXft2iUA5s2bZ8nsnjIlty5lqtSRI0ek7vjx4yVFNJIU7XVh1xErKHAjXdn5fuWqzZs3L0QFbkh9IJPaUX7gLqa+npurMbC6MPOUsSwdFRR4R6eQcXlW4nogtiowFZOdmwpwOliYjx1264QJE5A12E+SZ4kFXREWoEEkkWoTJ040ZBJlLEtHbW3e2RCTElZNAW1FIcETc57BqZLakdb6xwPZpHS6o6TqCs+ePdOpD1LKSFrH7Vddau/evVJ/9OjRQTvg0rxsdv7zWgIGKXZjeDDzO2XYdPuPlNe2Hz9+tGfOnBFmnqRlboeqUGtrq121apWAHTp0qIJOTDWsej7qKSG/ZTxV+hQpbGojNw0DGiZjG90Hnj59KmC5B/Tv35/HiUTwfNaQynwZkcsiHjNmTPmcOXP4TOurr/E5K+IiBDaDvoSZD1mYUic3VyCYS5cuyVhwH/Pnzx8pCxlc1yuLyoPympqa87QGKFLo9Jpk/6vW5wkXYCwCh+zEzKdhDannqQDVL+SbFB9AuWGW8op69he+z1BnYrGYwR4hnU+aNMl8/fo1dLac0b0pM4aY+QprSi9fvixmRKfeQT17o3bZkmuhvd3b4Jnfs2ePWHvatGmSpvB9d0b+AbM+l1KB8idPnnBgvphkH35CoBOgMt1FXYZVf/78abdt2yZASkpKMgXPem44lXVQ0djYyD5j7gAURCWC5SQyTUW0/vXr1+3ixYsFtFoei1meHeume9ZwWsHjaYF/e8AGWREAi99y/egaooz+rem3b9/M48ePDfYGc/ToURln+vTpBrMvedaLQIq1gAp0i2BxWYzspLm52Tx48MDgDcs8evTIfP782fz9+9c8f/7c4N0iGIehkgtYwQcFWWSoQAstBYp8clPwPMOcPXvWbN++3Tx8+DAURnFxsenbt6/cEX358kVmJ7RiZkLFKqfDrBYxfZ3E81NFRUXgrzNnzrS8JuGZvqioyA4aNMjCRYNy4Eu1y3aqw3opOGkRRw6juthfv34dDIKd3KY4hEkdhscMQmTQXwrwLNcwSkUkjBaePHlSwhAMykuntKSW//79u50/f74MSKvrgIwmCpZ5fdbyHkg1AjWir0Luas0vXrxQx2X8gyicWAZAUnj48GFz48YNM2vWLFm4bvRhBdZlZCEzr+XhPUeSargiZu+SGIe5av9+s00tjEGTSMv05DhixAg7ePDgwPrETeYMYNFavMwIcz1QpuXdTOXyC31UgwPq8jgNSwYKHThwQMDA+gFg9BTkcTudBJayHlAi/DiNwW9hd7zuq5PWjXjUPX36tFRl3CdBM0lxOWvwMmLwAmOqq6vNtWvXhJmnjGWs0w1S9yFW71o+01dKnYFXr16JdfEdwCKuB5amdfU2gTOUSDprrJPlTLjhs9Mrpb7A8KW+wR846a1M/f/u3bsCWg9gsIQAKiwsFDnP9DgSSzfY4CyZRBkjEuuzbhZKqPs0oI98MCmPIYVxlYLYpk2bamBhZA3wUpxMOIyJUKMRgMhzr17eqWT58uUGr4SBTOWUrVixIpBLJtqPAqpBM4ZSYlaZ+LEgSXWxpTNw//59saLe56MTsSZulUXOZ/9OVc79evanjGVk1o04A/oWVof2JD1KeE/+r7pS6NWiroF3794JCL54u6DRh8X9vpRt2bKl02cnhmjK3DrMZ8iZXS2iM5PuclcVwOkyuP7AK2ASCL3XXLZsmT127Jgw8wSrZRkCZxv6vfp+JfKktGEs7fW6KnH8+HEBNHv2bEkT3UGjEQaTcqZhMrc8JE/gemyg35O40ELdR0r9n5QfONSf1Y0YcRhO0S5JEboT1wlZXYv1EpXVtglp1h840I+Qd+Dx8p0+MakSuIIX0DoLiDaBImgWKJQhYLetLljK1PJE4mLic5fkzkTSRz7E945169bJwFRCYzx6dcFkmtdNSs85dB/1ebpMZPCqXafPrBs2bKjjTuxTHF9VYviQIYuMmxM/0vETEY4LmQJXP5c+fOUZKkt8APT5rMH7fZjQD90a67mwDx48SMtx6rnouLl0hMwIrcwy1mFdtbYqyx22CqzEaNPlgtXKmaRJfzXYuXNnPa9IGFrv3btncUVpFy5cSEBqWYIkE7RrZQXNtB68FsydlUTQuieJIN1PNhpyIAJSKsNRuXz37t2L8O47A3/kKH758qWBQgYf+HgmkXpwO63/ARm+jFwFXwB7p0pkQIl9e9I0v9kowO7S/t2mvLy8GJ+XhuJqpcBX4H/7u81/1jKjxQy/8v0AAAAASUVORK5CYII="; // CONCATENATED MODULE: ./src/image.js
  /* harmony default export */ const src_image = () => {
    const element = document.createElement("img");
    element.src = yinyang;

    return element;
  }; // CONCATENATED MODULE: ./src/app.js
  document.body.appendChild(component());
  document.body.appendChild(src_image());
  /******/
})();

And this is what it should look like on your file browser:

Output


Original article source at: https://masteringjs.io

#webpack 

Use Webpack's Url Loader with Example
Lawrence  Lesch

Lawrence Lesch

1668122160

Starter Kit with Zero-config for Building A Library in TypeScript

TypeScript library starter

A starter project that makes creating a TypeScript library extremely easy.

Usage

git clone https://github.com/alexjoverm/typescript-library-starter.git YOURFOLDERNAME
cd YOURFOLDERNAME

# Run npm install and write your library name when asked. That's all!
npm install

Start coding! package.json and entry files are already set up for you, so don't worry about linking to your main file, typings, etc. Just keep those files with the same name.

Features

Importing library

You can import the generated bundle to use the whole library generated by this starter:

import myLib from 'mylib'

Additionally, you can import the transpiled modules from dist/lib in case you have a modular library:

import something from 'mylib/dist/lib/something'

NPM scripts

  • npm t: Run test suite
  • npm start: Run npm run build in watch mode
  • npm run test:watch: Run test suite in interactive watch mode
  • npm run test:prod: Run linting and generate coverage
  • npm run build: Generate bundles and typings, create docs
  • npm run lint: Lints code
  • npm run commit: Commit using conventional commit style (husky will tell you to use it if you haven't :wink:)

Excluding peerDependencies

On library development, one might want to set some peer dependencies, and thus remove those from the final bundle. You can see in Rollup docs how to do that.

Good news: the setup is here for you, you must only include the dependency name in external property within rollup.config.js. For example, if you want to exclude lodash, just write there external: ['lodash'].

Automatic releases

Prerequisites: you need to create/login accounts and add your project to:

Prerequisite for Windows: Semantic-release uses node-gyp so you will need to install Microsoft's windows-build-tools using this command:

npm install --global --production windows-build-tools

Setup steps

Follow the console instructions to install semantic release and run it (answer NO to "Do you want a .travis.yml file with semantic-release setup?").

Note: make sure you've setup repository.url in your package.json file

npm install -g semantic-release-cli
semantic-release-cli setup
# IMPORTANT!! Answer NO to "Do you want a `.travis.yml` file with semantic-release setup?" question. It is already prepared for you :P

From now on, you'll need to use npm run commit, which is a convenient way to create conventional commits.

Automatic releases are possible thanks to semantic release, which publishes your code automatically on github and npm, plus generates automatically a changelog. This setup is highly influenced by Kent C. Dodds course on egghead.io

Git Hooks

There is already set a precommit hook for formatting your code with Prettier :nail_care:

By default, there are two disabled git hooks. They're set up when you run the npm run semantic-release-prepare script. They make sure:

This makes more sense in combination with automatic releases

FAQ

Array.prototype.from, Promise, Map... is undefined?

TypeScript or Babel only provides down-emits on syntactical features (class, let, async/await...), but not on functional features (Array.prototype.find, Set, Promise...), . For that, you need Polyfills, such as core-js or babel-polyfill (which extends core-js).

For a library, core-js plays very nicely, since you can import just the polyfills you need:

import "core-js/fn/array/find"
import "core-js/fn/string/includes"
import "core-js/fn/promise"
...

What is npm install doing on first run?

It runs the script tools/init which sets up everything for you. In short, it:

  • Configures RollupJS for the build, which creates the bundles
  • Configures package.json (typings file, main file, etc)
  • Renames main src and test files

What if I don't want git-hooks, automatic releases or semantic-release?

Then you may want to:

  • Remove commitmsg, postinstall scripts from package.json. That will not use those git hooks to make sure you make a conventional commit
  • Remove npm run semantic-release from .travis.yml

What if I don't want to use coveralls or report my coverage?

Remove npm run report-coverage from .travis.yml

Resources

Projects using typescript-library-starter

Here are some projects that use typescript-library-starter:

Download Details:

Author: Alexjoverm
Source Code: https://github.com/alexjoverm/typescript-library-starter 
License: MIT license

#typescript #library #webpack 

Starter Kit with Zero-config for Building A Library in TypeScript
Monty  Boehm

Monty Boehm

1667649120

Skpm: A Utility to Build and Publish Sketch Plugins

Skpm - Sketch Plugin Manager

A utility to create, build and publish sketch plugins.

Installation

Important: Node.js > V6.x is a minimum requirement. You also need the command line tools installed.

npm install -g skpm

Usage

skpm create my-plugin

The above command pulls the template from skpm/skpm, prompts for some information, and generates the project at ./my-plugin/.

Create a new plugin

skpm create <plugin-name>

--name        The plugin display name.
--cwd         A directory to use instead of $PWD.
--force       Force option to create the directory for the new app. [boolean] [default: false]
--template    The repository hosting the template to start from.    [string]  [default: skpm/skpm]
--git         Initialize version control using git.                 [boolean] [default: true]
--install     Installs dependencies.                                [boolean] [default: true]

A note on templates

The purpose of official skpm plugin templates are to provide opinionated development tooling setups so that users can get started with actual plugin code as fast as possible. However, these templates are un-opinionated in terms of how you structure your plugin code and what libraries you use in addition to skpm.

Current available official templates include:

💁 Tip: Any Github repo with a 'template' folder can be used as a custom template: skpm create <project-name> --template=<username>/<repository>

Build the plugin

Once the installation is done, you can run some commands inside the project folder:

npm run build

To watch for changes:

npm run watch

Additionally, if you wish to run the plugin every time it is built:

npm run start

View the plugin's log

To view the output of your console.log, you have a few different options:

  • Use the sketch-dev-tools
  • Open Console.app and look for the sketch logs
  • Look at the ~/Library/Logs/com.bohemiancoding.sketch3/Plugin Output.log file

Skpm provides a convenient way to do the latter:

skpm log

  -f, -F        The `-f` option causes tail to not stop when end of file is
                reached, but rather to wait for additional data to be appended
                to the input.                       [boolean] [default: "false"]
  --number, -n  Shows `number` lines of the logs.                       [number]

Publish the plugin on the registry

To publish a new version of the plugin to the registry:

skpm publish <new-version> | major | minor | patch | premajor | preminor | prepatch | prerelease

  --repo-url          Specify the repository URL (default to the one specified
                      in package.json).                                 [string]
  --skip-release      Do not create a release on GitHub.com.           [boolean]
  --open-release, -o  Open the newly created release on GitHub.com.    [boolean]
  --skip-registry     Do not publish to the plugins registry if not already
                      present.                                         [boolean]
  --download-url      Specify the new version's download URL (default to the
                      asset of the release created on GitHub.com).      [string]

The exact order of execution (without options) is as follows:

  • Run the preversion script
  • Bump version in package.json as requested (patch, minor, major, etc).
  • Run the version script
  • Commit and tag
  • Run the postversion script.
  • Run the prepublish or build script
  • Zip the folder specified in the main field
  • Create a draft release on GitHub
  • Upload the zip to GitHub
  • Publish the release
  • Remove the zip
  • Check the sketchplugins/plugin-directory repo to see if the plugin is already there. If not, open a PR to add it.

Download Details:

Author: skpm
Source Code: https://github.com/skpm/skpm 
License: MIT license

#sketch #plugin #registry #webpack 

Skpm: A Utility to Build and Publish Sketch Plugins
Toby Rogers

Toby Rogers

1667535508

Turbopack: The Rust-based successor to Webpack

Turbopack will be the Web’s next-generation bundler. Turbopack is built on a new incremental architecture for the fastest possible development experience. Turbopack only bundles the minimum assets required in development, so startup time is extremely fast.

Vercel's mission is to provide the speed and reliability innovators need to create at the moment of inspiration. Last year, we focused on speeding up the way Next.js bundles your apps.

Each time we moved from a JavaScript-based tool to a Rust-based one, we saw enormous improvements. We migrated away from Babel, which resulted in 17x faster transpilation. We replaced Terser, which resulted in 6x faster minification to reduce load times and bandwidth usage.

There was one hurdle left: Webpack. Webpack has been downloaded over 3 billion times. It’s become an integral part of building the Web, but it's time to go faster and scale without limits.

Today, we’re launching Turbopack: our successor to Webpack.

Led by the creator of Webpack, Tobias Koppers, Turbopack will be the Web’s next-generation bundler. We’re building it with high-performance bare-metal tooling—open source today, for all frameworks in the future.

Try out the alpha of Turbopack in Next.js 13 today with next dev --turbo.

How fast is Turbopack?

Turbopack is built on a new incremental architecture for the fastest possible development experience. On large applications, it shows updates 10x faster than Vite and 700x faster than Webpack. On even larger applications, the difference is greater—often 20x faster than Vite.

Turbopack only bundles the minimum assets required in development, so startup time is extremely fast. On an application with 3,000 modules, Turbopack takes 1.8 seconds to boot up, while Vite takes 11.4 seconds.

To learn more, read the docs on how Turbopack bundles and view the benchmarks.

Why is Turbopack so fast?

Turbopack’s architecture takes the lessons learned from tools like Turborepo and Google’s Bazel, both of which focus on using caches to never do the same work twice.

Turbopack is built on Turbo: an open-source, incremental memoization framework for Rust. Turbo can cache the result of any function in the program. When the program is run again, functions won't re-run unless their inputs have changed. This granular architecture enables your program to skip large amounts of work, at the level of the function.

An incremental reactive system with the speed of Rust? Turbopack is unstoppable.

To learn more, check out our explainer on Turbo.

The future of Turbo

To start, Turbopack will be used for the Next.js 13 development server. It will power lightning-fast HMR, and it will support React Server Components natively, as well as TypeScript, JSX, CSS, and more.

Turbopack will eventually also power Next.js production builds, both locally and in the cloud. We’ll be able to share Turbo's cache across your entire team, using Vercel Remote Caching.

Webpack users can also expect an incremental migration path into the Rust-based future with Turbopack.

We couldn’t be more excited about the future of the Turbo ecosystem, as we push to help you iterate faster and create at the moment of inspiration.

Explore the Turbopack alpha in Next.js 13 today.

Original article source at https://vercel.com

#turbopack #webpack #rust #nextjs #webdev 

Turbopack: The Rust-based successor to Webpack
Edward Jackson

Edward Jackson

1667359744

Learn Webpack 5 for Beginners

In this tutorial, you'll learn how to setup & configure Webpack 5 from scratch. Learn how to configure modern front-end tools together to create a complete Webpack starter kit for your projects. Learn Webpack 5 along with other modern tools like Babel, Jest, ESLint, & Prettier.

In this course, you will learn how to set up and configure Webpack 5 from scratch. We start with an empty directory and built up a complete Webpack starter kit, line by line. By the end of the course, we will have built a modern front-end starter kit with tools like Jest for unit testing, ESLint for linting, Prettier for formatting, and a whole bunch more.

Along the way, we will learn all about Webpack configurations for different environments like development & production, loaders, plugins, etc. Throughout the course, I teach you how to read and navigate Webpack's documentation so you not only understand the concepts but also understand where to go to learn more. Each project has its own specific needs, and by teaching you how to read the docs, you will now be able to configure Webpack to fit your specific project needs.

What you’ll learn:

  •        How to setup & configure Webpack 5 from scratch. You will also learn how to configure modern front-end tools together to create a complete Webpack starter kit for your projects.

Are there any course requirements or prerequisites?

  •        A basic understanding of JavaScript

Who this course is for:

  •        Web developers of all levels

#webpack #programming 

Learn Webpack 5 for Beginners
Reid  Rohan

Reid Rohan

1667166420

Razzle: Create Server-rendered Universal JavaScript Applications

Razzle

Universal JavaScript applications are tough to setup. Either you buy into a framework like Next.js or Nuxt, fork a boilerplate, or set things up yourself. Aiming to fill this void, Razzle is a tool that abstracts all the complex configuration needed for building SPA's and SSR applications into a single dependency--giving you the awesome developer experience of create-react-app, but then leaving the rest of your app's architectural decisions about frameworks, routing, and data fetching up to you. With this approach, Razzle not only works with React, but also Preact, Vue, Svelte, and Angular, and most importantly......whatever comes next.

Getting Started

Visit https://razzlejs.org/getting-started to get started with Razzle.

Examples

Razzle has many examples, we might have one that fits your needs

See: The examples

Documentation

Visit https://razzlejs.org/ to view the documentation.

Getting help

If you get stuck, check out Razzle's GitHub Discussions. In addition, #razzle-afterjs on the Formium Community Discord Server is a great way to get help quickly too.

Contributing

Please see our CONTRIBUTING.md.

Inspiration

Contributors

Thanks goes to these wonderful people (emoji key):

  • Jared Palmer - @jaredpalmer
    • Contributions: question, code, design, doc, example, ideas, review, test, tool
  • Nima Arefi - @Nimaa77
    • Contributions: question, code, doc, example, ideas, review, test, tool
  • Øyvind Saltvik - @fivethreeo
    • Contributions: question, code, example, ideas, review, test, tool
  • Jari Zwarts - @jariz
    • Contributions: question, code, ideas, plugin, review
  • Dan Abramov - @gaearon
    • Contributions: code, ideas
  • Eric Clemmons - @ericclemmons
    • Contributions: code, ideas
  • Zino Hofmann - @HofmannZ
    • Contributions: example
  • Lucas Terra - @lucasterra
    • Contributions: code, example, plugin
  • Ray Andrew - @rayandrews
    • Contributions: code, example, plugin
  • Heithem Moumni - @heithemmoumni
    • Contributions: code, example, plugin

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

Download Details:

Author: jaredpalmer
Source Code: https://github.com/jaredpalmer/razzle 
License: MIT license

#typescript #react #javascript #webpack 

Razzle: Create Server-rendered Universal JavaScript Applications
Reid  Rohan

Reid Rohan

1667099460

Incremental Bundler, Build System Optimized for JavaScript, TypeScript

Turbo

Turbo is an next-generation toolchain for frontend development, written in Rust. It consists of 3 major parts:

  • Turbopack: an incremental bundler (the successor to Webpack)
  • Turborepo: an incremental build system
  • The Turbo engine: a low-level incremental computation and memoization engine

Getting Started

Visit https://turbo.build to get started with Turbopack and Turborepo.

Contributing

See CONTRIBUTING.md for more information.

Community

The Turbo community can be found on GitHub Discussions, where you can ask questions, voice ideas, and share your projects.

To chat with other community members, you can join the Turbo Discord

Our Code of Conduct applies to all Turbo community channels.

Who is using Turbo?

Turbo is used by the world's leading companies. Check out the Turbo Showcase to learn more.

Updates

Follow @turborepo on Twitter and for project updates

Security

If you believe you have found a security vulnerability in Turbo, we encourage you to responsibly disclose this and not open a public issue. We will investigate all legitimate reports. Email security@vercel.com to disclose any security vulnerabilities.

https://vercel.com/security

Download Details:

Author: Vercel
Source Code: https://github.com/vercel/turbo 
License: MPL-2.0 license

#typescript #javascript #webpack 

Incremental Bundler, Build System Optimized for JavaScript, TypeScript
Gordon  Taylor

Gordon Taylor

1661986200

A Webpack Plugin to inline Your Critical CSS & Lazy-load The Rest

Critters

Critters is a plugin that inlines your app's critical CSS and lazy-loads the rest.

critters

It's a little different from other options, because it doesn't use a headless browser to render content. This tradeoff allows Critters to be very fast and lightweight. It also means Critters inlines all CSS rules used by your document, rather than only those needed for above-the-fold content. For alternatives, see Similar Libraries.

Critters' design makes it a good fit when inlining critical CSS for prerendered/SSR'd Single Page Applications. It was developed to be an excellent compliment to prerender-loader, combining to dramatically improve first paint time for most Single Page Applications.

Features

  • Fast - no browser, few dependencies
  • Integrates with Webpack critters-webpack-plugin
  • Supports preloading and/or inlining critical fonts
  • Prunes unused CSS keyframes and media queries
  • Removes inlined CSS rules from lazy-loaded stylesheets

Installation

First, install Critters as a development dependency:

npm i -D critters

or

yarn add -D critters

Simple Example

import Critters from 'critters';

const critters = new Critters({
  // optional configuration (see below)
});

const html = `
  <style>
    .red { color: red }
    .blue { color: blue }
  </style>
  <div class="blue">I'm Blue</div>
`;

const inlined = await critters.process(html);

console.log(inlined);
// "<style>.blue{color:blue}</style><div class=\"blue\">I'm Blue</div>"

Usage with webpack

Critters is also available as a Webpack plugin called critters-webpack-plugin. npm

The Webpack plugin supports the same configuration options as the main critters package:

// webpack.config.js
+const Critters = require('critters-webpack-plugin');

module.exports = {
  plugins: [
+    new Critters({
+      // optional configuration (see below)
+    })
  ]
}

That's it! The resultant html will have its critical CSS inlined and the stylesheets lazy-loaded.

Usage

Critters

All optional. Pass them to new Critters({ ... }).

Parameters

  • options

Properties

  • path String Base path location of the CSS files (default: '')
  • publicPath String Public path of the CSS resources. This prefix is removed from the href (default: '')
  • external Boolean Inline styles from external stylesheets (default: true)
  • inlineThreshold Number Inline external stylesheets smaller than a given size (default: 0)
  • minimumExternalSize Number If the non-critical external stylesheet would be below this size, just inline it (default: 0)
  • pruneSource Boolean Remove inlined rules from the external stylesheet (default: false)
  • mergeStylesheets Boolean Merged inlined stylesheets into a single <style> tag (default: true)
  • additionalStylesheets Array<String> Glob for matching other stylesheets to be used while looking for critical CSS.
  • preload String Which preload strategy to use
  • noscriptFallback Boolean Add <noscript> fallback to JS-based strategies
  • inlineFonts Boolean Inline critical font-face rules (default: false)
  • preloadFonts Boolean Preloads critical fonts (default: true)
  • fonts Boolean Shorthand for setting inlineFonts + preloadFonts* Values:
    • true to inline critical font-face rules and preload the fonts
    • false to don't inline any font-face rules and don't preload fonts
  • keyframes String Controls which keyframes rules are inlined.* Values:
    • "critical": (default) inline keyframes rules used by the critical CSS
    • "all" inline all keyframes rules
    • "none" remove all keyframes rules
  • compress Boolean Compress resulting critical CSS (default: true)
  • logLevel String Controls log level of the plugin (default: "info")
  • logger object Provide a custom logger interface logger

Logger

Custom logger interface:

Type: object

Properties

  • trace function (String) Prints a trace message
  • debug function (String) Prints a debug message
  • info function (String) Prints an information message
  • warn function (String) Prints a warning message
  • error function (String) Prints an error message

LogLevel

Controls log level of the plugin. Specifies the level the logger should use. A logger will not produce output for any log level beneath the specified level. Available levels and order are:

  • "info" (default)
  • "warn"
  • "error"
  • "trace"
  • "debug"
  • "silent"

Type: ("info" | "warn" | "error" | "trace" | "debug" | "silent")

PreloadStrategy

The mechanism to use for lazy-loading stylesheets.

Note: JS indicates a strategy requiring JavaScript (falls back to <noscript> unless disabled).

  • default: Move stylesheet links to the end of the document and insert preload meta tags in their place.
  • "body": Move all external stylesheet links to the end of the document.
  • "media": Load stylesheets asynchronously by adding media="not x" and removing once loaded. JS
  • "swap": Convert stylesheet links to preloads that swap to rel="stylesheet" once loaded (details). JS
  • "swap-high": Use <link rel="alternate stylesheet preload"> and swap to rel="stylesheet" once loaded (details). JS
  • "js": Inject an asynchronous CSS loader similar to LoadCSS and use it to load stylesheets. JS
  • "js-lazy": Like "js", but the stylesheet is disabled until fully loaded.
  • false: Disables adding preload tags.

Type: (default | "body" | "media" | "swap" | "swap-high" | "js" | "js-lazy")

Similar Libraries

There are a number of other libraries that can inline Critical CSS, each with a slightly different approach. Here are a few great options:

Download Details:

Author: GoogleChromeLabs
Source Code: https://github.com/GoogleChromeLabs/critters 
License: Apache 2.0

#javascript #css #webpack 

A Webpack Plugin to inline Your Critical CSS & Lazy-load The Rest
Dexter  Goodwin

Dexter Goodwin

1661961600

Size-plugin: Track Compressed Webpack Asset Sizes Over Time

size-plugin 

Prints the gzipped sizes of your webpack assets and the changes since the last build.

size-plugin

🙋 Using Rollup? Check out the rollup-plugin-size port.

Installation

Install size-plugin as a development dependency using npm:

npm i -D size-plugin

Usage

Add an instance of the plugin to your webpack configuration:

// webpack.config.js
+ const SizePlugin = require('size-plugin');

module.exports = {
  plugins: [
+    new SizePlugin()
  ]
}

SizePlugin

new SizePlugin(options)

Parameters

  • options Object
    • options.pattern string? minimatch pattern of files to track
    • options.exclude string? minimatch pattern of files NOT to track
    • options.filename string? file name to save filesizes to disk
    • options.publish boolean? option to publish filesizes to size-plugin-store
    • options.writeFile boolean? option to save filesizes to disk
    • options.stripHash function? custom function to remove/normalize hashed filenames for comparison

Item

Properties

  • name string Filename of the item
  • sizeBefore number Previous size, in kilobytes
  • size number Current size, in kilobytes
  • sizeText string Formatted current size
  • delta number Difference from previous size, in kilobytes
  • deltaText string Formatted size delta
  • msg string Full item's default message
  • color string The item's default CLI color

Data

Properties

  • sizes Array<Item> List of file size items
  • output string Current buffered output

Download Details:

Author: GoogleChromeLabs
Source Code: https://github.com/GoogleChromeLabs/size-plugin 
License: Apache 2.0

#javascript #webpack

Size-plugin: Track Compressed Webpack Asset Sizes Over Time
Dexter  Goodwin

Dexter Goodwin

1661933880

Webpack Extract Translation Keys Plugin

Webpack Extract Translation Keys Plugin

Webpack provides an official plugin for managing translation using i18n-webpack-plugin, but in only allows for build-time translations by replacing strings in the source code.

This plugin serves a similar purposes, but instead of replacing translation keys with actual string values it just collects translation keys allowing you to know exactly which translations are necessary for your client side.

Approach like this also allows to provide dynamically generated translation bundles to the client allowing you to get real-time updates to translation without regenerating whole client side bundle.

This plugin also compatible with Webpack 5.

Usage

Configuration

First you need to install plugin:

npm install --save-dev webpack-extract-translation-keys-plugin

And then include it in your configuration:

// webpack.config.js

var ExtractTranslationKeysPlugin = require('webpack-extract-translation-keys-plugin');
module.exports = {
    plugins: [
        new ExtractTranslationKeysPlugin({
            functionName: '_TR_',
            output: path.join(__dirname, 'dist', 'translation-keys.json')
        })
    ]

    // rest of your configuration...
}

Now inside your module you can write something like this:

console.log(_TR_('translation-key-1'));
console.log(_TR_('translation-key-2'));

If you run webpack now, you should get dist/translation-keys.json file with following content:

{
    "translation-key-1": "translation-key-1",
    "translation-key-2": "translation-key-2"
}

It may seems like a waste to output a map with the keys and values being the same thing, the purpose is to keep the output format consistent with the times when the mangle option is enabled.

Output

if output string contains [name], one output file will be created per entry key at corresponding output

// ...
    plugins: [
        new ExtractTranslationKeysPlugin({
            output: path.join(__dirname, 'dist', '[name]/translation-keys.json')
        })
    ]
// ...

Key Mangling

In some applications translation keys are quite long, so for the situtations where you want to save some additional bytes in your application, you can enable mangling during the plugin initialization:

// ...
    plugins: [
        new ExtractTranslationKeysPlugin({
            mangle: true,
            functionName: '_TR_',
            output: path.join(__dirname, 'dist', 'translation-keys.json')
        })
    ]
// ...

This setting changes the behavior of the plugin to replace the key name with a minimal ascii-readable string.

In order to be able to map back to the original translation key, the plugin outputs mapping object with keys being original keys and the values being the mangled ones:

{ "translation-key-1": " ", "translation-key-2": "!" }

It's recommended to only enable mangling for production builds, as it makes the debugging harder and also may break hot reloading, depending on your setup.

Runtime

Since this plugin doesn't replace function with something else it's up to you to provide function that will actually handle translation in the runtime. It can be a globally defined function or you can use webpack.ProvidePlugin inside your configuration:

module.exports = {
    plugins: [
        new ExtractTranslationKeysPlugin({
            functionName: '__',
            output: path.join(__dirname, 'dist', 'translation-keys.json')
        }),
        new webpack.ProvidePlugin({
            '__': 'path/to/module/with/translation/function.js'
        })
    ]

    // rest of your configuration...
}

Default options

  • functionName : __
  • done : function (result) {}
  • output : false
  • mangle : false

Error handling

Plugin throw an error if you try to call the translation function without any arguments or with a non-string argument (e.g. a variable).

Release Notes

6.0.0

Support for Webpack 5, if you are using Webpack 4, please install 5.x.x version of this plugin. This can be done by running:

npm install --save-dev webpack-extract-translation-keys-plugin@5

5.0.0

Support for multiple output for multiple entries with [name] inside the output string. If [name] is not present, only one output file will be created for all entries

4.0.0

Support for Webpack 4, if you are using Webpack 3, please install 3.x.x version of this plugin. This can be done by running:

npm install --save-dev webpack-extract-translation-keys-plugin@3

3.0.0

Support for Webpack 2, if you are using Webpack 1, please install 2.x.x version of this plugin. This can be done by running:

npm install --save-dev webpack-extract-translation-keys-plugin@2

2.0.0

Support for key mangling. The format of the output without mangling has changed from array to a map. If you want to have old behavior, you can implement it using done callback option.

Download Details:

Author: Grassator
Source Code: https://github.com/grassator/webpack-extract-translation-keys 
License: Apache License

#javascript #webpack #extract 

Webpack Extract Translation Keys Plugin
Dexter  Goodwin

Dexter Goodwin

1661930040

Tapable: Just A Little Module for Plugins

Tapable

The tapable package expose many Hook classes, which can be used to create hooks for plugins.

const {
    SyncHook,
    SyncBailHook,
    SyncWaterfallHook,
    SyncLoopHook,
    AsyncParallelHook,
    AsyncParallelBailHook,
    AsyncSeriesHook,
    AsyncSeriesBailHook,
    AsyncSeriesWaterfallHook
 } = require("tapable");

Installation

npm install --save tapable

Usage

All Hook constructors take one optional argument, which is a list of argument names as strings.

const hook = new SyncHook(["arg1", "arg2", "arg3"]);

The best practice is to expose all hooks of a class in a hooks property:

class Car {
    constructor() {
        this.hooks = {
            accelerate: new SyncHook(["newSpeed"]),
            brake: new SyncHook(),
            calculateRoutes: new AsyncParallelHook(["source", "target", "routesList"])
        };
    }

    /* ... */
}

Other people can now use these hooks:

const myCar = new Car();

// Use the tap method to add a consument
myCar.hooks.brake.tap("WarningLampPlugin", () => warningLamp.on());

It's required to pass a name to identify the plugin/reason.

You may receive arguments:

myCar.hooks.accelerate.tap("LoggerPlugin", newSpeed => console.log(`Accelerating to ${newSpeed}`));

For sync hooks, tap is the only valid method to add a plugin. Async hooks also support async plugins:

myCar.hooks.calculateRoutes.tapPromise("GoogleMapsPlugin", (source, target, routesList) => {
    // return a promise
    return google.maps.findRoute(source, target).then(route => {
        routesList.add(route);
    });
});
myCar.hooks.calculateRoutes.tapAsync("BingMapsPlugin", (source, target, routesList, callback) => {
    bing.findRoute(source, target, (err, route) => {
        if(err) return callback(err);
        routesList.add(route);
        // call the callback
        callback();
    });
});

// You can still use sync plugins
myCar.hooks.calculateRoutes.tap("CachedRoutesPlugin", (source, target, routesList) => {
    const cachedRoute = cache.get(source, target);
    if(cachedRoute)
        routesList.add(cachedRoute);
})

The class declaring these hooks need to call them:

class Car {
    /**
      * You won't get returned value from SyncHook or AsyncParallelHook,
      * to do that, use SyncWaterfallHook and AsyncSeriesWaterfallHook respectively
     **/

    setSpeed(newSpeed) {
        // following call returns undefined even when you returned values
        this.hooks.accelerate.call(newSpeed);
    }

    useNavigationSystemPromise(source, target) {
        const routesList = new List();
        return this.hooks.calculateRoutes.promise(source, target, routesList).then((res) => {
            // res is undefined for AsyncParallelHook
            return routesList.getRoutes();
        });
    }

    useNavigationSystemAsync(source, target, callback) {
        const routesList = new List();
        this.hooks.calculateRoutes.callAsync(source, target, routesList, err => {
            if(err) return callback(err);
            callback(null, routesList.getRoutes());
        });
    }
}

The Hook will compile a method with the most efficient way of running your plugins. It generates code depending on:

  • The number of registered plugins (none, one, many)
  • The kind of registered plugins (sync, async, promise)
  • The used call method (sync, async, promise)
  • The number of arguments
  • Whether interception is used

This ensures fastest possible execution.

Hook types

Each hook can be tapped with one or several functions. How they are executed depends on the hook type:

Basic hook (without “Waterfall”, “Bail” or “Loop” in its name). This hook simply calls every function it tapped in a row.

Waterfall. A waterfall hook also calls each tapped function in a row. Unlike the basic hook, it passes a return value from each function to the next function.

Bail. A bail hook allows exiting early. When any of the tapped function returns anything, the bail hook will stop executing the remaining ones.

Loop. When a plugin in a loop hook returns a non-undefined value the hook will restart from the first plugin. It will loop until all plugins return undefined.

Additionally, hooks can be synchronous or asynchronous. To reflect this, there’re “Sync”, “AsyncSeries”, and “AsyncParallel” hook classes:

Sync. A sync hook can only be tapped with synchronous functions (using myHook.tap()).

AsyncSeries. An async-series hook can be tapped with synchronous, callback-based and promise-based functions (using myHook.tap(), myHook.tapAsync() and myHook.tapPromise()). They call each async method in a row.

AsyncParallel. An async-parallel hook can also be tapped with synchronous, callback-based and promise-based functions (using myHook.tap(), myHook.tapAsync() and myHook.tapPromise()). However, they run each async method in parallel.

The hook type is reflected in its class name. E.g., AsyncSeriesWaterfallHook allows asynchronous functions and runs them in series, passing each function’s return value into the next function.

Interception

All Hooks offer an additional interception API:

myCar.hooks.calculateRoutes.intercept({
    call: (source, target, routesList) => {
        console.log("Starting to calculate routes");
    },
    register: (tapInfo) => {
        // tapInfo = { type: "promise", name: "GoogleMapsPlugin", fn: ... }
        console.log(`${tapInfo.name} is doing its job`);
        return tapInfo; // may return a new tapInfo object
    }
})

call: (...args) => void Adding call to your interceptor will trigger when hooks are triggered. You have access to the hooks arguments.

tap: (tap: Tap) => void Adding tap to your interceptor will trigger when a plugin taps into a hook. Provided is the Tap object. Tap object can't be changed.

loop: (...args) => void Adding loop to your interceptor will trigger for each loop of a looping hook.

register: (tap: Tap) => Tap | undefined Adding register to your interceptor will trigger for each added Tap and allows to modify it.

Context

Plugins and interceptors can opt-in to access an optional context object, which can be used to pass arbitrary values to subsequent plugins and interceptors.

myCar.hooks.accelerate.intercept({
    context: true,
    tap: (context, tapInfo) => {
        // tapInfo = { type: "sync", name: "NoisePlugin", fn: ... }
        console.log(`${tapInfo.name} is doing it's job`);

        // `context` starts as an empty object if at least one plugin uses `context: true`.
        // If no plugins use `context: true`, then `context` is undefined.
        if (context) {
            // Arbitrary properties can be added to `context`, which plugins can then access.
            context.hasMuffler = true;
        }
    }
});

myCar.hooks.accelerate.tap({
    name: "NoisePlugin",
    context: true
}, (context, newSpeed) => {
    if (context && context.hasMuffler) {
        console.log("Silence...");
    } else {
        console.log("Vroom!");
    }
});

HookMap

A HookMap is a helper class for a Map with Hooks

const keyedHook = new HookMap(key => new SyncHook(["arg"]))
keyedHook.for("some-key").tap("MyPlugin", (arg) => { /* ... */ });
keyedHook.for("some-key").tapAsync("MyPlugin", (arg, callback) => { /* ... */ });
keyedHook.for("some-key").tapPromise("MyPlugin", (arg) => { /* ... */ });
const hook = keyedHook.get("some-key");
if(hook !== undefined) {
    hook.callAsync("arg", err => { /* ... */ });
}

Hook/HookMap interface

Public:

interface Hook {
    tap: (name: string | Tap, fn: (context?, ...args) => Result) => void,
    tapAsync: (name: string | Tap, fn: (context?, ...args, callback: (err, result: Result) => void) => void) => void,
    tapPromise: (name: string | Tap, fn: (context?, ...args) => Promise<Result>) => void,
    intercept: (interceptor: HookInterceptor) => void
}

interface HookInterceptor {
    call: (context?, ...args) => void,
    loop: (context?, ...args) => void,
    tap: (context?, tap: Tap) => void,
    register: (tap: Tap) => Tap,
    context: boolean
}

interface HookMap {
    for: (key: any) => Hook,
    intercept: (interceptor: HookMapInterceptor) => void
}

interface HookMapInterceptor {
    factory: (key: any, hook: Hook) => Hook
}

interface Tap {
    name: string,
    type: string
    fn: Function,
    stage: number,
    context: boolean,
    before?: string | Array
}

Protected (only for the class containing the hook):

interface Hook {
    isUsed: () => boolean,
    call: (...args) => Result,
    promise: (...args) => Promise<Result>,
    callAsync: (...args, callback: (err, result: Result) => void) => void,
}

interface HookMap {
    get: (key: any) => Hook | undefined,
    for: (key: any) => Hook
}

MultiHook

A helper Hook-like class to redirect taps to multiple other hooks:

const { MultiHook } = require("tapable");

this.hooks.allHooks = new MultiHook([this.hooks.hookA, this.hooks.hookB]);

Download Details:

Author: Webpack
Source Code: https://github.com/webpack/tapable 
License: MIT license

#javascript #webpack 

Tapable: Just A Little Module for Plugins
Reid  Rohan

Reid Rohan

1661877960

Webpack Google Closure Compiler and Closure Library Plugin

Closure-webpack-plugin

This plugin supports the use of Google's Closure Tools with webpack.

Install

You must install both the google-closure-compiler package as well as the closure-webpack-plugin.

npm install --save-dev closure-webpack-plugin google-closure-compiler

Usage example

const ClosurePlugin = require('closure-webpack-plugin');

module.exports = {
  optimization: {
    minimizer: [
      new ClosurePlugin({mode: 'STANDARD'}, {
        // compiler flags here
        //
        // for debugging help, try these:
        //
        // formatting: 'PRETTY_PRINT'
        // debug: true,
        // renaming: false
      })
    ]
  }
};

Options

  • platform - native, java or javascript. Controls which version to use of closure-compiler. By default the plugin will attempt to automatically choose the fastest option available.
    • JAVASCRIPT does not require the JVM to be installed. Not all flags are supported.
    • JAVA utilizes the jvm. Utilizes multiple threads for parsing and results in faster compilation for large builds.
    • NATIVE only available on linux or MacOS. Faster compilation times without requiring a JVM.
  • mode - STANDARD (default) or AGGRESSIVE_BUNDLE. Controls how the plugin utilizes the compiler.
    • STANDARD mode, closure-compiler is used as a direct replacement for other minifiers as well as most Babel transformations.
    • AGGRESSIVE_BUNDLE mode, the compiler performs additional optimizations of modules to produce a much smaller file
  • childCompilations - boolean or function. Defaults to false. In order to decrease build times, this plugin by default only operates on the main compilation. Plugins such as extract-text-plugin and html-webpack-plugin run as child compilations and usually do not need transpilation or minification. You can enable this for all child compilations by setting this option to true. For specific control, the option can be set to a function which will be passed a compilation object.
    Example: function(compilation) { return /html-webpack/.test(compilation.name); }.
  • output - An object with either filename or chunkfilename properties. Used to override the output file naming for a particular compilation. See https://webpack.js.org/configuration/output/ for details.
  • test - An optional string or regular expression to determine whether a chunk is included in the compilation
  • extraCommandArgs - Optional string or Array of strings to pass to the google-closure-compiler plugin. Can be used to pass flags to the java process.

Compiler Flags

The plugin controls several compiler flags. The following flags should not be used in any mode:

  • module_resolution
  • output_wrapper
  • dependency_mode
  • create_source_map
  • module
  • entry_point

Aggressive Bundle Mode

In this mode, the compiler rewrites CommonJS modules and hoists require calls. Some modules are not compatible with this type of rewriting. In particular, hoisting will cause the following code to execute out of order:

const foo = require('foo');
addPolyfillToFoo(foo);
const bar = require('bar');

Aggressive Bundle Mode utilizes a custom runtime in which modules within a chunk file are all included in the same scope. This avoids the cost of small modules.

In Aggressive Bundle Mode, a file can only appear in a single output chunk. Use the Split Chunks Plugin to split duplicated files into a single output chunk. If a module is utilized by more than one chunk, the plugin will move it up to the first common parent to prevent code duplication.

The concatenatedModules optimization is not compatible with this mode since Closure-Compiler performs an equivalent optimization). The plugin will emit a warning if this optimization is not disabled.

Multiple Output Languages

You can add the plugin multiple times. This easily allows you to target multiple output languages. Use ECMASCRIPT_2015 for modern browsers and ECMASCRIPT5 for older browsers.

Use the output option to change the filenames of specific plugin instances.

Use <script type="module" src="es6_out_path.js"> to target modern browsers and <script nomodule src="es5_out_path.js"> for older browsers.

See the es5 and es6 output demo for an example.

Other tips for Use

  • Don't use babel at the same time - closure-compiler is also a transpiler. If you need features not yet supported by closure-compiler, have babel only target those features. Closure Compiler can transpile async/await - you don't need babel for that functionality either.

Closure Library Plugin

In order for webpack to recognize goog.require, goog.provide, goog.module and related primitives, a separate plugin is shipped.

const ClosurePlugin = require('closure-webpack-plugin');

module.exports = {
  plugins: [
    new ClosurePlugin.LibraryPlugin({
      closureLibraryBase: require.resolve(
        'google-closure-library/closure/goog/base'
      ),
      deps: [
        require.resolve('google-closure-library/closure/goog/deps'),
        './public/deps.js',
      ],
    })
  ]
};

The plugin adds extra functionality to support using Closure Library without Closure Compiler. This is typically used during development mode. When the webpack mode is production, only dependency information is provided to webpack as Closure Compiler will natively recognize the Closure Library primitives.

The Closure Library Plugin is only compatible with the AGGRESSIVE_BUNDLE mode of the Closure-Compiler webpack plugin.

Options

  • closureLibraryBase - (optional) string. Path to the base.js file in Closure-Library.
  • deps - (optional) string or Array. Closures style dependency mappings. Typically generated by the depswriter.py script included with Closure-Library.
  • extraDeps - (optional) Object. Mapping of namespace to file path for closure-library provided namespaces.

Note: This is the webpack 4 branch.

Closure-Compiler is a full optimizing compiler and transpiler. It offers unmatched optimizations, provides type checking and can easily target transpilation to different versions of ECMASCRIPT.

Closure-Library is a utility library designed for full compatibility with Closure-Compiler.

Older Versions

For webpack 3 support, see https://github.com/webpack-contrib/closure-webpack-plugin/tree/webpack-3


Download Details:

Author: Webpack-contrib
Source Code: https://github.com/webpack-contrib/closure-webpack-plugin 
License: MIT license

#javascript #webpack #plugin 

Webpack Google Closure Compiler and Closure Library Plugin
Dexter  Goodwin

Dexter Goodwin

1661867652

Reduce Moment-timezone Data Size for A Webpack Build

moment-timezone-data-webpack-plugin 

Oof, that’s a clunky name, but at least it’s descriptive.

This is a plugin for webpack which reduces data for moment-timezone.

Why is this needed?

Moment Timezone is a comprehensive library for working with time zones in JavaScript. But that comprehensiveness comes with a file size cost. The full time zone data file is 903KiB raw, or 36KiB minified and gzipped (as of moment-timezone version 0.5.23).

That’s a lot of data to send to someone’s browser, especially if you don’t need all of it. Some of the time zones have data dating back to the 19th century. Thankfully there is an API to produce a custom data bundle containing only the time zone definitions you require.

Unfortunately, if you’re building your project with webpack, you don’t get to use a custom data bundle. A webpack build uses the Node.js version of moment-timezone, which automatically includes all the time zone data. Even if you configure Moment Timezone to use a custom data bundle at run-time, the full data file will still be present in your JavaScript bundle.

This plugin allows you to configure which time zone data you want. Any unwanted data is then automatically stripped from the compiled JS bundle at build time.

Use it in combination with the moment-locales-webpack-plugin to further reduce the compiled JS bundle size.

Example

Take a super-simple file which does nothing more than require('moment-timezone'). Building this with webpack in production mode results in over 1 MiB of minified JS code.

What if you only need the default English locale, and time zone data for Australia and New Zealand from 2018 to 2028? (This is a realistic scenario from a recent project.)

Running webpack in production mode results in the following file sizes:

ConfigurationRaw sizeGzipped
Default1164 KiB105 KiB
Strip locales959 KiB (~82%)56 KiB (~53%)
Strip tz data265 KiB (~23%)69 KiB (~66%)
Strip locales & tz data60 KiB (~5%)20 KiB (~19%)

(Testing done with webpack@4.28.3, moment@2.23.0, moment-timezone@0.5.23.)

Even if you still need all the time zones available, reducing the data to a much smaller date range can produce significant file size savings. Building the above example file with data for all zones from 2018 to 2028 produces a file size of 288KiB, or 74KiB gzipped.

⚠️ Make sure you know what you’re doing ❗️️

Dealing with time zones can be tricky, and bugs can pop up in unexpected places. That’s doubly true when you’re auto-removing data at build time. When using this plugin, make absolutely sure that you won’t need the data you’re removing.

For example, if you know for certain that your web site/application...

  1. ...will never deal with past dates & times earlier than a certain point (e.g. the launch date of the application).
  2. ...will never deal with future dates & times beyond a certain point (e.g. details of a specific event).
    • It’s (relatively) safe to remove any data beyond that date (using the endYear option).
  3. ...will only deal with a fixed set of time zones (e.g. rendering times relative to a set of physical buildings in a single country).

However, if you’re allowing users to choose their time zone preference — with no theoretical limit on the range of dates you’ll handle — then you’re going to need all the data you can get.

If you’re in doubt about whether to include some data, err on the side of caution and include it.

Usage

Installation

Using npm:

npm install --save-dev moment-timezone-data-webpack-plugin

Or using yarn:

yarn add --dev moment-timezone-data-webpack-plugin

Configuration

Add the plugin to your webpack config file:

const MomentTimezoneDataPlugin = require('moment-timezone-data-webpack-plugin');

module.exports = {
  plugins: [
    new MomentTimezoneDataPlugin({
      // options
    }),
  ]
};

Plugin options

There are four available options to filter the time zone data. At least one option must be provided.

  • startYear (integer) — Only include data from this year onwards.
  • endYear (integer) — Only include data up to (and including) this year.
  • matchZones — Only include data for time zones with names matching this value. matchZones can be any of these types:
    • string — Include only this zone name as an exact match (e.g. 'Australia/Sydney').
    • regexp — Include zones with names matching the regular expression (e.g. /^Australia\//).
    • array (of the above types) — Include zones matching any of the values of the array. Each value can be a string or a regular expression, which will be matched following the rules above.
  • matchCountries — Only include data for time zones associated with specific countries, as determined by Moment Timezone’s zonesForCountry() API. matchCountries works with ISO 3166 2-letter country codes, and can be any of these types:
    • string — Include zones for this country code as an exact match (e.g. 'AU').
    • regexp — Include zones for country codes matching the regular expression (e.g. /^A|NZ/).
    • array (of the above types) — Include zones for country codes matching any of the values of the array. Each value can be a string or a regular expression, which will be matched following the rules above.

NOTE: The matchCountries option will only work when used with moment-timezone version 0.5.28 or later. If this option is used with a non-compliant version of moment-timezone, an error will be thrown.

All filtering options are AND (a.k.a. conjunction) filters — that is, they become more restrictive as each one is applied. Only zone data that match all the provided filters will be added to the final output. For this reason, it’s probably safer to provide only one of matchZones or matchCountries; providing both is allowed, but you may not get the results you expect.

There are also some non-filtering options that can be provided to configure other behaviour around file locations.

  • cacheDir (string) — A path where the generated files will be cached. If not provided, the files will be cached in an automatically-generated location.
  • momentTimezoneContext (regexp) — A regexp matching a context where moment-timezone is located. The timezone file will be replaced only if it is located in this context. Other instances of the timezone file out of this context will not be touched. This is useful in case you are using a version stored outside of node_modules (e.g. if module or vendor directory is vendor\moment-timezone the context could be matched for example with vendor[\\/]moment-timezone$). Defaults to /node_modules[\\/]moment-timezone$/.

Version support

This plugin has been tested with and officially supports the following dependencies:

  • Node.js 8 or higher
  • webpack 4 and 5
  • moment-timezone v0.1.0 or higher

It theoretically supports older versions of webpack (as it uses built-in webpack plugins internally), but this hasn’t been tested.

Examples

All zones, with a limited date range

const currentYear = new Date().getFullYear();
const plugin = new MomentTimezoneDataPlugin({
  startYear: currentYear - 2,
  endYear: currentYear + 10,
});

All data for a specific zone

const plugin = new MomentTimezoneDataPlugin({
  matchZones: 'America/New_York',
});

All data for a specific country

const plugin = new MomentTimezoneDataPlugin({
  // Includes 'Pacific/Auckland' and 'Pacific/Chatham'
  matchCountries: 'NZ',
});

Limited data for a set of zones (single regular expression)

const plugin = new MomentTimezoneDataPlugin({
  matchZones: /Europe\/(Belfast|London|Paris|Athens)/,
  startYear: 2000,
  endYear: 2030,
});

Limited data for a set of zones (array of values)

const plugin = new MomentTimezoneDataPlugin({
  matchZones: [/^Australia/, 'Pacific/Auckland', 'Etc/UTC'],
  startYear: 2000,
  endYear: 2030,
});

Limited data for a set of countries

const plugin = new MomentTimezoneDataPlugin({
  matchCountries: ['US', 'CA'],
  startYear: 2000,
  endYear: 2030,
});

Download Details:

Author: Gilmoreorless
Source Code: https://github.com/gilmoreorless/moment-timezone-data-webpack-plugin 
License: MIT License 

#javascript #timezone #webpack 

Reduce Moment-timezone Data Size for A Webpack Build
Dexter  Goodwin

Dexter Goodwin

1661863811

Easily Remove Unused Moment.js Locales with Webpack

moment-locales-webpack-plugin  

Easily remove unused Moment.js locales when building with webpack

Why

75% (160 minified KBs)¹ of Moment.js’ size are files used for localization. They are always included when you build your app with webpack.

You don’t need most of these files if your app is only available in a few languages. Use this plugin to strip these KBs and optimize the app!

¹ – tested with Moment.js 2.18.1

Install

npm install --save-dev moment-locales-webpack-plugin

Usage

// webpack.config.js
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');

module.exports = {
    plugins: [
        // To strip all locales except “en”
        new MomentLocalesPlugin(),

        // Or: To strip all locales except “en”, “es-us” and “ru”
        // (“en” is built into Moment and can’t be removed)
        new MomentLocalesPlugin({
            localesToKeep: ['es-us', 'ru'],
        }),
    ],
};

Plugin Options

localesToKeep: String[]

An array of locales to keep bundled (other locales would be removed).

Locale names follow Moment.js behavior – if a specific locale name (e.g. ru-ru) is absent, but a more generic locale (ru) is available, the generic one will be kept bundled.

ignoreInvalidLocales: Boolean

A flag to ignore invalid or unsupported locales in the localesToKeep array.

Be careful! A typo in the localesToKeep array with this flag enabled will silently exclude the desired locale from your bundle.

Related projects

Contributing

See CONTRIBUTING.md for how to contribute.

Download Details:

Author: iamakulov
Source Code: https://github.com/iamakulov/moment-locales-webpack-plugin 
License: MIT

#javascript #webpack 

Easily Remove Unused Moment.js Locales with Webpack
Hoang  Kim

Hoang Kim

1661170810

Cách Xây Dựng Thư Viện Bằng JavaScript, Webpack Và Workspaces

Hướng dẫn xây dựng thư viện bằng cách sử dụng không gian làm việc Webpack và Yarn. 

Yêu cầu

Đây là những yêu cầu. Nhưng nếu bạn kiểm tra kho lưu trữ, có tài liệu tham khảo và giải thích. Tôi đã cố gắng cung cấp lời giải thích tốt nhất có thể, nhưng nó hiếm khi hoàn hảo hoặc chung chung cho tất cả mọi người. Có các bước để xây dựng và kiểm tra mã để bạn có thể thử nghiệm với nó. Rất nhiều tài nguyên để đào và tìm hiểu cách thức hoạt động của nó.

  • Làm quen với JavaScript.
  • Một số quen thuộc với Webpack. Mã sử ​​dụng cấu hình tối thiểu khoảng 15 dòng mã.
  • Một số quen thuộc với không gian làm việc của Yarn.

Mục đích

Xây dựng một ứng dụng trình bày các gói xây dựng bằng JavaScript và monorepo.

Phân tách logic bằng cách sử dụng monorepo

Sử dụng gói mô-đun để tạo một gói phụ thuộc vào một gói khác chưa được xuất bản lên NPM.

Thông số kỹ thuật

Để ngắn gọn, chúng ta hãy làm một chiếc máy tính bỏ túi.

Chúng tôi sẽ xây dựng một ứng dụng máy tính có bốn hoạt động:

+    add
-    subtract
*    multiply
/    divide

Chúng tôi đang xây dựng một máy tính. Chúng tôi chia logic thành bốn gói.

Máy tính của chúng tôi sẽ sử dụng bốn gói. Chúng tôi sử dụng webpack để xây dựng gói máy tính của mình.

Khởi tạo kho lưu trữ

Run (Lệnh sau là viết tắt của yarn install) :

yarn

Gói xây dựng

Phát triển và sản xuất

yarn build

Chạy thử nghiệm

Đầu tiên xây dựng gói.

Để kiểm tra trong trình duyệt:

  1. Đi tới __tests__thư mục
  2. Mở useDevBuild.htmltrong trình duyệt
  3. Mở useProdBuild.htmltrong trình duyệt
  4. Mở bảng điều khiển dành cho nhà phát triển và xác minh rằng đầu ra ở đó

Để kiểm tra trong chạy nodejs:

kiểm tra sợi

Người giới thiệu

Kết quả

Sử dụng không gian làm việc sợi, mọi gói sẽ được cài đặt trong thư mục gốc node_modules. Điều đó cho phép nhiều nhóm làm việc trên từng gói riêng lẻ. Hoặc một nhóm làm việc trên mỗi gói. Việc chuyển từ monorepo sang multirepo dễ dàng hơn so với cách khác. Hãy tra cứu điều này trên internet, đừng nghe lời tôi.

Sử dụng webpack, điểm nhập là một máy tính. Nó sẽ tra cứu mã máy tính đang sử dụng và tạo ra một bản dựng.

Chúng tôi thử nghiệm bản dựng sau đó. Bản dựng là mô-đun UMD có nghĩa là chúng ta có thể sử dụng nó trong môi trường trình duyệt và NodeJS. Tra cứu trên internet về các gói cho NodeJS và Trình duyệt. Họ yêu cầu shimming .

Chúng tôi kiểm tra các bản xuất được đặt tên và mặc định trong NodeJS, bằng cách in kết quả. Trong trình duyệt, chúng tôi cũng làm như vậy.

Khai báo một thư mục dưới dạng thư mục không gian làm việc:

{
  "name": "calculator-demo",
  "version": "0.1.0",
  "workspaces": ["packages/*"]
}

Chìa khóa ở đây là workspacestài sản. Khai báo tất cả các thư mục trong packagesdưới dạng không gian làm việc. Mỗi người trong số họ cần phải có package.json.

Liên kết: https://faun.pub/build-library-using-javascript-webpack-and-workspaces-e71310ad8db8

#javascript #webpack  #workspace 

Cách Xây Dựng Thư Viện Bằng JavaScript, Webpack Và Workspaces