Giter Site home page Giter Site logo

vercel / webpack-asset-relocator-loader Goto Github PK

View Code? Open in Web Editor NEW
95.0 52.0 35.0 2.27 MB

Used in ncc while emitting and relocating any asset references

Home Page: https://npmjs.com/@vercel/webpack-asset-relocator-loader

License: MIT License

JavaScript 100.00%

webpack-asset-relocator-loader's Introduction

Asset Relocator Loader for Webpack

Build Status codecov

Asset relocation loader used in ncc for performing Node.js builds while emitting and relocating any asset references.

Usage

Installation

npm i -g @vercel/webpack-asset-relocator-loader

Usage

Add this loader as a Webpack plugin for any JS files.

Any .node files included will also support binary relocation.

{
  target: "node",
  output: {
    libraryTarget: "commonjs2"
  },
  module: {
    rules: [
      {
        // For node binary relocations, include ".node" files as well here
        test: /\.(m?js|node)$/,
        // it is recommended for Node builds to turn off AMD support
        parser: { amd: false },
        use: {
          loader: '@vercel/webpack-asset-relocator-loader',
          options: {
            // optional, base folder for asset emission (eg assets/name.ext)
            outputAssetBase: 'assets',
            // optional, restrict asset emissions to only the given folder.
            filterAssetBase: process.cwd(),
            // optional, permit entire __dirname emission
            // eg `const nonAnalyzable = __dirname` can emit everything in the folder
            emitDirnameAll: false,
            // optional, permit entire filterAssetBase emission
            // eg `const nonAnalyzable = process.cwd()` can emit everything in the cwd()
            emitFilterAssetBaseAll: false,
            // optional, custom functional asset emitter
            // takes an asset path and returns the replacement
            // or returns false to skip emission
            customEmit: (path, { id, isRequire }) => false | '"./custom-replacement"',
            // optional, a list of asset names already emitted or
            // defined that should not be emitted
            existingAssetNames: [],
            wrapperCompatibility: false, // optional, default
            // build for process.env.NODE_ENV = 'production'
            production: true, // optional, default is undefined
            cwd: process.cwd(), // optional, default
            debugLog: false, // optional, default
          }
        }
      }
    ]
  }
}

Assets will be emitted using emitAsset, with their references updated in the code by the loader to the new output location.

Asset Permissions and Symlinks

Asset symlinks and permissions are maintained in the loader, but aren't passed to Webpack as emit doesn't support these.

This information can be obtained from the loader through the API calls getAssetMeta() and getSymlinks():

const relocateLoader = require('webpack-asset-relocator-loader');

webpack({...}).run((err, stats) => {
  const assetMeta = relocateLoader.getAssetMeta();
  const symlinks = relocateLoader.getSymlinks();
});

They will always contain the most recent build state.

Caching

When using Webpack 5 caching, asset permissions need to be maintained through their own cache, and the public path needs to be injected into the build.

To ensure these cases work out, make sure to run initAssetCache in the build, with the options.outputAssetBase argument:

const relocateLoader = require('webpack-asset-relocator-loader');

webpack({
  // ...

  plugins: [
    {
      apply(compiler) {
        compiler.hooks.compilation.tap("webpack-asset-relocator-loader", compilation => {
          relocateLoader.initAssetCache(compilation, outputAssetBase);
        });
      }
    }
  ]
});

How it Works

Asset Relocation

Assets are detected using static analysis of code, based on very specific triggers designed for common Node.js workflows to provide build support for a very high (but not perfect) level of compatibility with existing Node.js libraries.

  • process.cwd(), __filename, __dirname, path.*(), require.resolve are all statically analyzed when possible.
  • File emissions for exact asset paths
  • Whole directory asset emissions for exact directory paths
  • Wildcard asset emissions for variable path expressions

When an asset is emitted, the pure expression referencing the asset path is replaced with a new expression to the relocated asset and the asset emitted. In the case of wildcard emission, the dynamic parts of the expression are maintained.

Binary Relocation

Node binary loading conventions cover the following triggers for binary relocations:

  • require('bindings')(...)
  • nbind.init(..)
  • node-pre-gyp include patterns

Any shared libraries loaded by these binaries will also be emitted as well.

Node.js Compatibility Features

In addition to asset relocation, this loader also provides a couple of compatibility features for Webpack Node.js builds as part of its analysis.

These include:

  • require.main === module checks are retained for the entry point being built.
  • options.wrapperCompatibility: Automatically handles common AMD / Browserify wrappers to ensure they are properly built by Webpack. See the utils/wrappers.js file for the exact transformations currently provided.
  • require.resolve support in the target environment, while also supporting emission in the build environment.
  • Dynamic require statements are analyzed to exact paths wherever possible, and when not possible to analyze, turned into dynamic requires in the target environment.

webpack-asset-relocator-loader's People

Contributors

adriencohen avatar dependabot[bot] avatar fregante avatar goloveychuk avatar guybedford avatar huv1k avatar silverwind avatar styfle avatar timer avatar valbendan avatar yichi-yang avatar yurynix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webpack-asset-relocator-loader's Issues

Protobuf include emission support

Currently we emit .proto files independently, but because they typically include references to other proto files, we need to ensure that these transitive references can be maintained with the asset emission process.

Module build Failed

I'm trying to use ELECTRONJS + ReactJS + Typescript with 'puppeteer-core' it works perfectly when I don't use puppeteer
but when I add the puppeteer
returns this error below, can anyone help me?

import chrome from 'chrome-aws-lambda'
import puppeteer from 'puppeteer-core'

export async function Auth(url: string) {
  const browser = await puppeteer.launch({
    args: chrome.args,
    executablePath: await chrome.executablePath,
    headless: chrome.headless
  })
  const page = await browser.newPage()
  await page.goto(url)
  await page.screenshot({ path: 'example.png' })
  await browser.close()
  return true
}
  ipcMain.on('message', async (_, message) => {
    await Auth(url) //if I commit this line the application works normally again
  })

image

[Windows] Path parts in strings replaced with undefined

OS: Windows 11
webpack-asset-relocator-loader version: 1.7.2
Node version: 16.15.0

Configuration

 {
    test: /\.(m?js|node)$/,
    parser: { amd: false },
    use: {
      loader: '@vercel/webpack-asset-relocator-loader',
      options: {
        outputAssetBase: 'native_modules',
      },
    },
  },

What is the behavior that I'm seeing

Any string containing paths to the project has that pieceof the string replaced with undefined.

What I would expect to see

Path parts not replaced with undefined.

Example

In this example, the project is located at C:\Users\example-user\web\example-project, and a file exists at .\src\some-path\some-file.txt

var path = 'C:\\Users\\example-user\\web\\example-project\\src\\some-path\\some-file.txt';
console.log(path);
// => undefinedsome-file.txt

More Information

This is an Electron Forge application. The problem has been narrowed down to this plugin (removing the plugin fixes the issue)

Module not found: Error: Can't resolve '@vercel/webpack-asset-relocator-loader'

I'm starting out with electron-forge, and am using the webpack plugin. When I request a maker (dmg) to package and make, I get the following error type whenever there is a 'require' statement in my code:
Module not found: Error: Can't resolve '@vercel/webpack-asset-relocator-loader' in 'pathname'
ERROR in ./main.js 206:17-38
Would appreciate help to resolve this.

Better esm support

I noticed in #27 esm support was added but only in the cases of require = require('esm')(module);.

What doesn't seem to be supported is this.

const _require = require('esm')(module);
const myModule = _require('my-module');

@guybedford any chance you could help on this?

Invalid dependencies have been reported by plugins or loaders for this module. All reported dependencies need to be absolute paths.

error

WARNING in ./node_modules/iohook/index.js
Invalid dependencies have been reported by plugins or loaders for this module. All reported dependencies need to be absolute paths.
Invalid dependencies may lead to broken watching and caching.
As best effort we try to convert all invalid values to absolute paths and converting globs into context dependencies, but this is deprecated behavior.
Loaders: Pass absolute paths to this.addDependency (existing files), this.addMissingDependency (not existing files), and this.addContextDependency (directories).
Plugins: Pass absolute paths to fileDependencies (existing files), missingDependencies (not existing files), and contextDependencies (directories).
Globs: They are not supported. Pass absolute path to the directory as context dependencies.
The following invalid values have been reported:

image

import

image

the dependence's source code

image

loader

image

output

image

Upgrade to ncc 0.14.1

This project will produce a build bug if built with ncc 0.14.0 or below due to the lack of support for vercel/ncc#271.

I cheated and used a patched ncc version to publish the last release here, so have pushed a commit at d781529 which will not support installation / publishing until the new ncc version is available with the fix.

Support for symlinks

It seems like Webpack 5 now has support for emitting symbolic links by resolving them, if resolve.symlinks is not explicitly set to false.
Maybe this module could move out the logic that discards detected symlinks thanks to the change? A specific use case I am thinking of is npm link or file: installation of local packages.

Output directory structure for native modules for Electron - any risks here?

Hi!

First of all, thanks for the great project, I made my Rush monorepo work with electron-builder thanks to that!

I wanted to ask about the situation with the output directory structure for Electron. I saw electron-forge uses a directory called "narive_modules" but I couldn't find any information on why. Besides that, in the code itself, there is a comment:

// retain directory depth structure for binaries for rpath to work out

It seems important as well but I still can't understand how it matters. (do some packages have tendencies to do some relative path operations with native modules?)

I would be very grateful if someone can explain the reasons for all of that, I just want to be sure that nothing could ever break in my app if I use a different output structure.

PS. I actually did a modification that allows prefixing the output path with the package name so instead of output structure like:

  • main.js
  • build/Release/keytar.node
  • prebuilds/win32-x64/node.napi.node

we can get:

  • main.js
  • keytar/build/Release/keytar.node
  • ffi-napi/prebuilds/win32-x64/node.napi.node

(my fork is based on @MarshallOfSound which makes the package work with modules like node-ffi)

Better special cases abstraction

Creating this as a refactoring issue. Despite the separate special cases module, the special cases in the main asset loader have still continued to grow. We should create the necessary API hook to ensure that all special cases are handled via configuration / separation so that we aren't directly littering the main core with these.

Uncaught ReferenceError: __dirname is not defined

When used in the electron project it cause this bug with nodeIntegration: false.

In this last line:

/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "/";
/******/
/******/ 	// __webpack_hash__
/******/ 	__webpack_require__.h = function() { return hotCurrentHash; };
/******/ 	__webpack_require__.ab = __dirname + "/native_modules/";

โ†‘

Error on 2.x upgrade

I upgraded from 0.1.12 to 0.2.3 and I now get the following error:

Defining routes from exportPathMap
(node:32998) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'readableIdentifier' of null
    at Object.ModuleFilenameHelpers.createFilename (/Users/xxxx/my-website/node_modules/webpack/lib/ModuleFilenameHelpers.js:83:28)
...

There were no other changes to the code and the app still works when I revert to 0.1.12. I'm happy to provide a reproducible demo if needed :)

Yarn berry pnp support

I see that you're using resolve package, which does not work with pnp, and does not want to merge pnp support into repo.
To fix this, resolve maintainer created an api to hook into resolution.
Yarn team from their side created a patch, which applied when resolve installed.
https://github.dev/yarnpkg/berry/blob/5f123d0301030a29fa28ef89b1974c016edb50dc/packages/plugin-compat/extra/resolve/normalize-options.js#L1
This is what I have in yarn.lock

"resolve@patch:resolve@^2.0.0-next.3#~builtin<compat/resolve>":

But because assets relocator loader bundles resolve, it's not possible to apply a patch.
To fix this we need to make resolve external, does not bundle it, and declare it as dependency in package.json.
I can provide a pr.

Test fails on macOS

$ yarn test
yarn run v1.15.2
$ npm run build && jest
npm WARN lifecycle The node binary used for scripts is /var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/yarn--1552870982981-0.9442051424146831/node but npm is using /usr/local/bin/node itself. Use the `--scripts-prepend-node-path` option to include the path for the node binary npm was executed with.

> @zeit/[email protected] build /Users/styfle/Code/zeit/webpack-asset-relocator-loader
> ncc build src/asset-relocator.js

1290kB  dist/index.js
1290kB  [8752ms] - ncc 0.15.2
 FAIL  test/project.test.js
  โ— should correctly run webpack build project-chunking

    expect(received).toBe(expected) // Object.is equality

    Expected: "asset.txt"
    Received: ""

      at eval (eval at <anonymous> (test/project.test.js:13:7), <anonymous>:5:39)
      at eval (test/project.test.js:13:7)
      at Object.<anonymous>.it (test/project.test.js:11:5)

 PASS  test/index.test.js (8.422s)

Test Suites: 1 failed, 1 passed, 2 total
Tests:       1 failed, 31 passed, 32 total
Snapshots:   0 total
Time:        8.988s
Ran all test suites.
error Command failed with exit code 1.

Puppeteer support

This would need to be supported as its own emission case, inlining the logic from lib/Launcher.js:

const browserFetcher = new BrowserFetcher(this._projectRoot);
...
browserFetcher.revisionInfo(this._preferredRevision);

where this._preferredRevision comes from the package.json file in node_modules/puppeteer-core/package.json puppeteer.chrome_revision property.

The internal logic of BrowserFetcher then does a join on the metadata to construct the path of the form - ${base}${os}-${revision} where base is node_modules/puppeteer/.local-chromium. Simply emitting this folder would be sufficient for support.

Wildcard require paths

With the latest updates we now support wildcard assets, but we still don't support wildcard requires like the following pattern:

function load (path) {
  return require(`./modules/${path}`);
}

where path is effectively unknown, so we could be loading any file from the folder.

One way to support this would be to glob the output folder, and then convert that information into an inlined rewriting operation (say if modules contained file1.js and file2.js):

const __wildcard_1 = (file) => {
  if (file === 'file1' || file === 'file1.js')
    return require('./modules/file1.js');
  else if (file === 'file2' || file === 'file2.js')
    return require('./modules/file2.js');
  return require('./modules/' + file);
};
function load (path) {
  return __wildcard_1(file);
}

with the above Webpack can then fully statically analyze the requires giving full build support.

Errors out when options isn't specified

Using the following config:

{
  amd: false,
  target: 'node',
  output: {
    libraryTarget: 'commonjs2'
  },
  module: {
    rules: [
      {
        test: /\.(m?js|node)$/,
        use: {
          loader: '@vercel/webpack-asset-relocator-loader'
        }
      }
    ]
  }
}

Results in the following error:

node_modules/@vercel/webpack-asset-relocator-loader/dist/index.js:28408
  injectPathHook(this._compilation, options.outputAssetBase);
                                            ^

TypeError: Cannot read property 'outputAssetBase' of null
    at Object.module.exports (node_modules/@vercel/webpack-asset-relocator-loader/dist/index.js:28408:45)

Passing an empty options object fixes it:

        use: {
          loader: '@vercel/webpack-asset-relocator-loader',
+         options: {}
        }

Cannot relocate fsevents binary

Platform: macOS

package.json

{
  "name": "ncc-test",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "chokidar": "^2.1.2"
  }
}

index.js

const chokidar = require("chokidar");

chokidar.watch(".", {}).on("all", (event, path) => {
  console.log(event, path);
});
ncc build index.js

Error:

Tims-MacBook:ncc-test timfish$ ncc build index.js 
ncc: Module directory "/Users/timfish/Documents/Repositories/ncc-test/node_modules/fsevents/node_modules/node-pre-gyp/lib" attempted to require "aws-sdk" but could not be resolved, assuming external.
ncc: Module directory "/Users/timfish/Documents/Repositories/ncc-test/node_modules/fsevents/node_modules/node-pre-gyp/lib" attempted to require "aws-sdk" but could not be resolved, assuming external.
ncc: Module directory "/Users/timfish/Documents/Repositories/ncc-test/node_modules/fsevents/node_modules/node-pre-gyp/lib" attempted to require "aws-sdk" but could not be resolved, assuming external.
ncc: Module directory "/Users/timfish/Documents/Repositories/ncc-test/node_modules/fsevents/node_modules/node-pre-gyp/lib/util" attempted to require "npm" but could not be resolved, assuming external.
ncc: Module directory "/Users/timfish/Documents/Repositories/ncc-test/node_modules/fsevents/node_modules/node-pre-gyp/lib/util" attempted to require "node-gyp" but could not be resolved, assuming external.
ncc: Module directory "/Users/timfish/Documents/Repositories/ncc-test/node_modules/fsevents/node_modules/node-pre-gyp/lib" attempted to require "request" but could not be resolved, assuming external.
   0kB  dist/node-pre-gyp/bin/node-pre-gyp.cmd
   0kB  dist/nw-pre-gyp/package.json
   0kB  dist/node-pre-gyp/lib/util/nw-pre-gyp/package.json
   0kB  dist/node-pre-gyp/contributing.md
   1kB  dist/node-pre-gyp/appveyor.yml
   1kB  dist/node-pre-gyp/LICENSE
   1kB  dist/nw-pre-gyp/index.html
   1kB  dist/node-pre-gyp/lib/util/nw-pre-gyp/index.html
   2kB  dist/node-pre-gyp/package.json
   2kB  dist/package.json
   3kB  dist/node-pre-gyp/bin/node-pre-gyp
  13kB  dist/node-pre-gyp/CHANGELOG.md
  24kB  dist/node-pre-gyp/lib/util/abi_crosswalk.json
  30kB  dist/node-pre-gyp/README.md
1660kB  dist/index.js
1738kB  [10697ms] - ncc 0.15.2

Suspect it's due to this in the fsevents dependency:

var path = require('path');
var binary = require('node-pre-gyp');
var Native = require(binary.find(path.join(__dirname, 'package.json')));

Binary relocation not working for bindings and node-pre-gyp

I tried using both binding and node-pre-gyp include patterns and both are not working even though the documentation states that they should be supported.

The setup I'm trying to get working is main project "foo" with a dependency on "bar" where the native binaries are in "bar".

What I tried:

  • Using bindings in "bar" with the file located at lib/binding/node-v72-darwin-x64/bindings.node.
  • Using bindings in "bar" with the file located at build/Release/bindings.node.
  • Using node-pre-gyp pattern in "bar" with the file located at lib/binding/node-v72-darwin-x64/bindings.node and calling require(`../../../lib/binding/node-v${process.versions.modules}-${process.platform}-${process.arch}/bindings.node`).

Interestingly, for the last case if I call instead require(`../../../lib/binding/node-v72-${os.platform()}-${os.arch()}/bindings.node`) it works properly. It looks like os is supported for dynamic paths but not process? I wonder if the same issue applies to bindings which would explain why it also doesn't work.

process.cwd() + package.json should be dynamic

Context

path.resolve(process.cwd(), 'package.json');

if <project_dir>/package.json exists, then the code emits path.resolve(t.ab + 'package.json') which t is treated as static. but in most case (I guess), it means to resolve the runtime project's package.json

Related: vercel/ncc#444

The issue could be any filename accidentally exists in the project ncc build. but the package.json is the most outstanding one.

Inconsitant handling of path seperators resulting in generateWildcardRequire generating invalid conditions

Bug Description

On Windows, generateWildcardRequire can generate invalid conditions due to inconsistent handling of path separators (/ vs \).

There's an active issue about this bug here: vercel/ncc#593. An example of generated buggy code (borrowed from /urbdyn/ncc-bug-1):

/***/ 71330:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

function __ncc_wildcard$0 (arg) {
  if (arg === "C:/code/urbdyn/ncc-bug-1/node_modules/knex/lib/dialects/") return __webpack_require__(19427);
  else if (arg === "C:/code/urbdyn/ncc-bug-1/node_modules/knex/lib/dialects/") return __webpack_require__(75941);
  else if (arg === "C:/code/urbdyn/ncc-bug-1/node_modules/knex/lib/dialects/") return __webpack_require__(17653);
  else if (arg === "C:/code/urbdyn/ncc-bug-1/node_modules/knex/lib/dialects/") return __webpack_require__(9051);
  else if (arg === "C:/code/urbdyn/ncc-bug-1/node_modules/knex/lib/dialects/") return __webpack_require__(25310);
  else if (arg === "C:/code/urbdyn/ncc-bug-1/node_modules/knex/lib/dialects/") return __webpack_require__(64482);
  else if (arg === "C:/code/urbdyn/ncc-bug-1/node_modules/knex/lib/dialects/") return __webpack_require__(97332);
  else if (arg === "C:/code/urbdyn/ncc-bug-1/node_modules/knex/lib/dialects/") return __webpack_require__(85370);
}

Cause

function generateWildcardRequire(dir, wildcardPath, wildcardParam, wildcardBlocks, log) {
const wildcardBlockIndex = wildcardBlocks.length;
const trailingWildcard = wildcardPath.endsWith(WILDCARD);
const wildcardIndex = wildcardPath.indexOf(WILDCARD);
const wildcardPrefix = wildcardPath.substr(0, wildcardIndex);
const wildcardSuffix = wildcardPath.substr(wildcardIndex + 1);
const endPattern = wildcardSuffix ? '?(.@(js|json|node))' : '.@(js|json|node)';
// sync to support no emission case
if (log)
console.log('Generating wildcard requires for ' + wildcardPath.replace(WILDCARD, '*'));
let options = glob.sync(wildcardPrefix + '**' + wildcardSuffix + endPattern, { mark: true, ignore: 'node_modules/**/*' });
if (!options.length)
return;
const optionConditions = options.map((file, index) => {
const arg = JSON.stringify(file.substring(wildcardPrefix.length, file.lastIndexOf(wildcardSuffix)));
let relPath = path.relative(dir, file).replace(/\\/g, '/');
if (!relPath.startsWith('../'))
relPath = './' + relPath;
let condition = index === 0 ? ' ' : ' else ';
if (trailingWildcard && arg.endsWith('.js"'))
condition += `if (arg === ${arg} || arg === ${arg.substr(0, arg.length - 4)}")`;
else if (trailingWildcard && arg.endsWith('.json"'))
condition += `if (arg === ${arg} || arg === ${arg.substr(0, arg.length - 6)}")`;
else if (trailingWildcard && arg.endsWith('.node"'))
condition += `if (arg === ${arg} || arg === ${arg.substr(0, arg.length - 6)}")`;
else
condition += `if (arg === ${arg})`;
condition += ` return require(${JSON.stringify(relPath)});`;
return condition;
}).join('\n');
wildcardBlocks.push(`function __ncc_wildcard$${wildcardBlockIndex} (arg) {\n${optionConditions}\n}`);
return `__ncc_wildcard$${wildcardBlockIndex}(${wildcardParam})`;
}

On Windows, wildcardPath uses \ as separators. In the example above:

wildcardPath = "C:\\SOME\\PATH\\node_modules\\knex\\lib\\dialects\\*\\index.js";
wildcardPrefix = "C:\\SOME\\PATH\\node_modules\\knex\\lib\\dialects\\";
wildcardSuffix = "\\index.js";

The options returned by glob.sync, however, are in POSIX format.

options = [
  "C:/SOME/PATH/node_modules/knex/lib/dialects/better-sqlite3/index.js",
  "C:/SOME/PATH/node_modules/knex/lib/dialects/cockroachdb/index.js",
  "C:/SOME/PATH/node_modules/knex/lib/dialects/mssql/index.js",
  // ...
];

As the result, file.lastIndexOf(wildcardSuffix) will always be -1, and file.substring(...) is just the prefix (but in POSIX format), which is obviously not right.

Also, the glob implementation asks for / regardless of POSIX or Windows, and passing Windows style wildcardPrefix + '**' + wildcardSuffix + endPattern could be considered invalid.

Proposed Fix

We normalize dir and wildcardPath to POSIX style, and use path.posix.relative instead of path.relative.
I implemented this very simple fix in this PR: #153
I'd like some code review to make sure I haven't messed up.

Nextjs native module different behavior in prod mode

Native module can't be found in prod mode.
Reproduce by cloning https://github.com/amarjanica/demo-nextjs-native-module

What works:

  1. start with npm run dev
  2. go to http://localhost:3000/hello

What doesn't work:

  1. npm run build && npm run start
  2. go to http://localhost:3000/hello

I get a MODULE_NOT_FOUND. it is expected in /.next/server/native-assets/index.node, although it's actually found in /.next/server/chunks/native-assets/index.node.
Locally I solved this by cloning your project and modifying this block asset-relocator.js. Depending on the NODE_ENV, I append chunks to the relBase.

Is this a bug?

Dynamic require of .json where file extension is not provided

Hi,
I'm trying to use ncc with the npm module "conventional-changelog-core" from the project https://github.com/conventional-changelog/conventional-changelog and found that the ncc_wildcards function does not seem to work if the arg passed in is missing the file extension (eg ".json"). It looks like the method generateWildcardRequire in "src/asset-relocator.js" is not recognizing that the arg coming in is extension-less. The offending file is https://github.com/conventional-changelog/conventional-changelog/blob/master/packages/conventional-changelog-core/lib/merge-config.js#L222 where it is calling require('../hosts/' + type). In this scenario "type" is either "github", "bitbucket" or "gitlab" but the actual file it is trying to pull in is "../hosts/github.json", "../hosts/bitbucket.json" or "../hosts/gitlab.json". The resulting ncc_wildcard function looks like

function __ncc_wildcard$0 (arg) {
  if (arg === "bitbucket.json") return __webpack_require__(749);
  else if (arg === "github.json") return __webpack_require__(520);
  else if (arg === "gitlab.json") return __webpack_require__(404);
}

but the actual function is called like this:

hostOpts = __ncc_wildcard$0(type)

where "type" is "github", "bitbucket" or "gitlab".

How to make it work with babel?

I'm trying to use escpos module with Electron. But some of the main js file uses class properties so I get this error:

image

How I can handle this with babel?

Dynamic wildcard analysis

With the PR in #39 we can now support wildcard requires like require('./local' + name), but for cases like:

const requirePath = './local' + name;
require(requirePath)

the wildcard analysis won't extend to the variable tracing.

We can add support for this by extending the variable analysis to not be known static values, but also partial values as well, although this does involve refactoring the value tracking system somewhat.

Semver 7 dependency analysis fails

I'd love to use NCC to bundle my Github Actions, but I'm running into an issue with Semver v7, which is a transitive dependency of some packages I use.

Semver 7 uses a pattern to only require() the things that are actually used:

lazyExport('valid', './functions/valid')

https://github.com/npm/node-semver/blob/70d9fb3f1c128227a3cd911867edb07a54260cad/index.js

ncc does not know that files like ./functions/valid should be bundled.

I tried to fix it here: goto-bus-stop@f2bae06
By rewriting to:

lazyExport('valid', require.resolve('./functions/valid'))

That does put the functions in the bundle, but now the way semver calls require() with a variable with a value that is not known at analysis time seems to be a problem. Instead of using __webpack_require__, it is output as a plain node.js require(), so it ends up doing stuff like require(8) which doesn't work.

At that point I'm stuck. Is there a way to make this pattern work already in ncc, and I'm just missing it?

I assume a more likely path to success is to get those ./functions/valid things output as separate bundles in the dist/ folder. Then the node.js require() with a rewritten path would just work. I'm not sure where to look for that though! The special cases file has access to emitAssetDirectories, but I don't think that bundles them?

I would appreciate any pointers!

Better relative asset path emission

The relative asset path emission doesn't work very well with variable output chunk folders.

The way to fix this would be to use a reference like __webpack_chunkname__ to ensure proper relative output.

Even better than having to do this at runtime, we could possibly do a custom generation like in https://github.com/webpack/webpack/blob/master/lib/ExtendedAPIPlugin.js#L37 to do a custom __rel_asset_base__ replacement of our own that does the correct backtracking.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.