TylorS / snowpack-plugin-hash

Apply content hashes to your production build
15 stars 2 forks source link

Build error when trying to use local font files #10

Open zackseuberling opened 3 years ago

zackseuberling commented 3 years ago

While trying to use local font files in my CSS, I run into an UnhandledPromiseRejectionWarning:

(node:40405) UnhandledPromiseRejectionWarning: Error: Can't resolve '/fonts/Inter-SemiBold.woff2'

My snowpack.config.js file:

module.exports = {
  mount: {
    _site: { url: "/", static: true },
    src: "/",
  },
  plugins: [
    "@snowpack/plugin-postcss",
    ["@snowpack/plugin-run-script", { cmd: "eleventy", watch: "$1 --watch" }],
    ["snowpack-plugin-hash"],
  ],
  optimize: {
    bundle: true,
    minify: true,
    target: "es2018",
  },
};

My CSS file (using postcss to convert the Tailwind imports):

@tailwind base;
@tailwind components;
@tailwind utilities;

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/Inter-SemiBold.woff2") format("woff2");
}

@font-face {
  font-family: "Inter";
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/Inter-SemiBoldItalic.woff2") format("woff2");
}

When I remove the @font-face rules, the build works as expected.

In my specific example, Inter happens to be available via Google Fonts, so adding an additional CSS link rule to the header could resolve it. This isn't always possible or always the ideal webfont loading solution, so I am wondering if there could be a solution for local webfonts.

DavidOliver commented 3 years ago

If I comment-out my @font-face rules, this then happens for me with local images, too. Snowpack 3.

const isDev = process.env.NODE_ENV === 'development';
const outDir = isDev ? 'web/build-dev' : 'web/build';

// We’re processing Stylus via its CLI in order to set the necessary config
const stylusCmd = `stylus src/style.styl --include-css --use ./node_modules/rupture --out ${outDir}`;

/** @type {import("snowpack").SnowpackUserConfig } */
module.exports = {
  mount: {
    'src': '/',
  },
  exclude: [
    '**/_*/**/*',
    '**/*.styl',
  ],
  plugins: [
    [
      '@snowpack/plugin-run-script',
      {
        cmd: stylusCmd,
        watch: `${stylusCmd} --watch --quiet`,
      },
    ],
    [
      'snowpack-plugin-hash',
      {
        hashLength: 8,
        assetManifest: 'manifest-test.json',
      }
    ]
  ],
  packageOptions: {
    source: 'local',
  },
  buildOptions: {
    out: outDir,
  },
};
david@pc:/m/projects/my_project/project$ tree -L 2 web/build/
web/build/
├── font
│   ├── ...
├── img
│   ├── photo-bg-laptop.jpg
├── script.js
├── _snowpack
│   ├── ...
├── style.css
└── tracking.js
david@pc:/m/projects/teaching_how2s_site/project$ grep photo-bg-laptop web/build/style.css
  background-image: url("/img/photo-bg-laptop.jpg");
david@pc:/m/projects/my_project/project$ npm run build

> my_project@3.1.0 build /m/projects/my_project/project
> snowpack build

[stylus] compiled web/build/style.css
[snowpack] ! building source files...
[snowpack] ✔ build complete [0.09s]
[snowpack] ! building dependencies...
[snowpack] ✔ dependencies ready! [2.52s]
[snowpack] ! verifying build...
[snowpack] ✔ verification complete [0.01s]
[snowpack] ! writing build to disk...
[snowpack] ! optimizing build...
[snowpack-plugin-hash] ℹ Hashing Directory /m/projects/my_project/project/web/build...
falling back to enhanced-resolve /img/photo-bg-laptop.jpg
(node:772) UnhandledPromiseRejectionWarning: Error: Can't resolve '/img/photo-bg-laptop.jpg' in '/m/projects/my_project/project/web/build'
    at finishWithoutResolve (/m/projects/my_project/project/node_modules/enhanced-resolve/lib/Resolver.js:293:18)
    at /m/projects/my_project/project/node_modules/enhanced-resolve/lib/Resolver.js:362:15
    at /m/projects/my_project/project/node_modules/enhanced-resolve/lib/Resolver.js:410:5
    at eval (eval at create (/m/projects/my_project/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
    at /m/projects/my_project/project/node_modules/enhanced-resolve/lib/Resolver.js:410:5
    at eval (eval at create (/m/projects/my_project/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:27:1)
    at /m/projects/my_project/project/node_modules/enhanced-resolve/lib/DescriptionFilePlugin.js:87:43
    at /m/projects/my_project/project/node_modules/enhanced-resolve/lib/Resolver.js:410:5
    at eval (eval at create (/m/projects/my_project/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
    at /m/projects/my_project/project/node_modules/enhanced-resolve/lib/Resolver.js:410:5
    at eval (eval at create (/m/projects/my_project/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /m/projects/my_project/project/node_modules/enhanced-resolve/lib/Resolver.js:410:5
    at eval (eval at create (/m/projects/my_project/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /m/projects/my_project/project/node_modules/enhanced-resolve/lib/Resolver.js:410:5
    at eval (eval at create (/m/projects/my_project/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /m/projects/my_project/project/node_modules/enhanced-resolve/lib/Resolver.js:410:5
(Use `node --trace-warnings ...` to show where the warning was created)
(node:772) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:772) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
DavidOliver commented 3 years ago

I just tried installing and using typed-content-hash at the command line. When running on the same build directory I get the same error. When running on a directory that has only one image, it runs successfully but the asset manifest file is {} and the image's filename is unchanged. (Perhaps this is expected in this situation, but I was imagining that any assets would be renamed with hashes whether or not they are mentioned in an existing map Sorry I'm hazy on how things are supposed to work.)

TylorS commented 3 years ago

Hey @DavidOliver, sorry for the slow reply. I'm sorry this appears to be broken, and thanks for reporting.

Would you happen to be able to create a git repo that I could use to recreate this issue to debug through?

TylorS commented 3 years ago

When running on a directory that has only one image, it runs successfully but the asset manifest file is {} and the image's filename is unchanged.

I missed this initially...but this is intentional. The only file types @typed/content-hash understands are .html .js .ts and .css right now in terms of parsing. However while it is parsing for dependencies within those files, if they point to other kinds of file extensions we can resolve they will also get content hashes

thdxr commented 3 years ago

Running into this issue as well - is there a way to tell the plugin only to try and process certain files?

TylorS commented 3 years ago

Hey @thdxr, I don't yet have the functionality in @typed/content-hash. I'm not totally sure when I'll have the time, but I'd gladly accept a PR for that change. In infrastructure/plugins the css/javascript/html.ts files all have a findDependencies function which would just need to be modified I think