添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

webpack is a module bundler for JavaScript. Front-end applications contain many types of assets such as JavaScript, (HOPEFULLY) Typescript, JSON, HTML, CSS, and images. webpack (after you've configure it to process files in a certain manner) will generate static assets, representing your applications modules so that they can be interpreted by a browser.

A "hook" in software development is a place in code that allows you to tap into a module to either provide different behavior or to react when something happens. webpack provides the following types of hooks:

  • Compiler hooks
  • Compilation hooks
  • ContextModuleFactory hooks
  • JavascriptParser hooks
  • NormalModuleFactory hooks
  • For an example scenario, let's pretend we want to make sure that, when we build our application, no file is outputted that contains the string MY_SUPER_SECRET . Perhaps we want to do this to provide a last line of defense from a developer including a sensitive value in our code and we want to prevent webpack from even compiling it. If that string is detected, we'd like webpack to:

  • throw an error.
  • not emit any files at any point during the build.
  • To do this, let's look at the shouldEmit compiler hook. This hook is called before assets are emitted and will allow us to error out and not emit assets if our validation fails.

    To start, let's create a new plugin class and add it to the plugins block of our webpack.config :

    // src/webpack.config.ts
    import { AssetValidatorPlugin } from './plugins/asset-validator-plugin';
    module.exports= {
        entry: {...},
        module:{...},
        plugins: [
            new AssetValidatorPlugin(),
        Enter fullscreen mode
        Exit fullscreen mode
    

    Note that, while I've defined my plugin in a separate class/file, you could include it in your webpack.config inline.

    Now, let's take a look at the plugin:

    // src/plugins/asset-validator-plugin.ts
    import * as webpack from 'webpack';
    export class AssetValidatorPlugin {
      apply(compiler: webpack.Compiler) {
        compiler.hooks.shouldEmit.tap('AssetValidatorPlugin', (compilation: webpack.compilation.Compilation) => {
          this.validateAssets(compilation);
      public validateAssets(compilation: webpack.compilation.Compilation) {
        const assets = Object.entries(compilation.assets);
        const regex = new RegExp('MY_SUPER_SECRET', 'g');
        // Loop through each asset and check to see if it contains any sensitive strings
        for (let i = 0; i < assets.length; i++) {
          const [fileName] = assets[i];
          const asset = compilation.getAsset(fileName);
          const source = asset.source.source();
          const contents = convertSourceToString(source);
          const matches = contents.match(regex);
          if (matches) {
            throw new Error(
              "Our tool has identified the presence of the string 'MY_SUPER_SECRET' in your compiled code. Compilation has been aborted."
        return true;
    // This function is only needed because asset.source.source() can be a string or ArrayBuffer
    const convertSourceToString = (source: string | ArrayBuffer): string => {
      if (typeof source === 'string') {
        return source;
      } else {
        return new TextDecoder().decode(source);
        Enter fullscreen mode
        Exit fullscreen mode
    

    So, let's review what is included our plugin. We've defined our plugin class and, within, are able to tap into the compiler.hooks.shouldEmit hook. In the hook callback, we simply call a validateAssets() function we've defined which loops through all assets that are part of the compilation and use regular expression matching to see if the string exists. We throw an error if it does, short-circuiting the compilation and not emitting any files. If it doesn't contain our special string, we'll return true, compilation will continue, emitting the packaged files as expected.

    If you have a need to pass any parameters to your plugin, that can easily be accomplished by defining a constructor in your plugin class like this:

    constructor(options: MyPluginOptions) {
        this.options = options;
        Enter fullscreen mode
        Exit fullscreen mode
                  Tricking Dependabot into allowing multiple update configs for one package ecosystem
                      #dependabot
                      #javascript
                      #github
                  How to inspect transient DOM elements
                      #javascript
                      #frontend
          

    Built on Forem — the open source software that powers DEV and other inclusive communities.

    Made with love and Ruby on Rails. DEV Community © 2016 - 2024.