Skip to content

Commit

Permalink
Fix to resovle dependencies with paths option in tsconfig parcel-bund…
Browse files Browse the repository at this point in the history
  • Loading branch information
Hyeonjae Park committed Feb 15, 2019
1 parent a2e38f9 commit f6b12ff
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 6 deletions.
1 change: 1 addition & 0 deletions packages/core/parcel-bundler/src/Asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class Asset {
this.buildTime = 0;
this.bundledSize = 0;
this.resolver = new Resolver(options);
this.resolvePaths = {};
}

shouldInvalidate() {
Expand Down
7 changes: 4 additions & 3 deletions packages/core/parcel-bundler/src/Bundler.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,8 @@ class Bundler extends EventEmitter {
return asset;
}

async resolveAsset(name, parent) {
let {path} = await this.resolver.resolve(name, parent);
async resolveAsset(name, parent, resolvePaths) {
let {path} = await this.resolver.resolve(name, parent, resolvePaths);
return this.getLoadedAsset(path);
}

Expand Down Expand Up @@ -471,7 +471,7 @@ class Bundler extends EventEmitter {
return this.getLoadedAsset(dep.resolved);
}

return await this.resolveAsset(dep.name, asset.name);
return await this.resolveAsset(dep.name, asset.name, asset.resolvePaths);
} catch (err) {
// If the dep is optional, return before we throw
if (dep.optional) {
Expand Down Expand Up @@ -574,6 +574,7 @@ class Bundler extends EventEmitter {
asset.generated = processed.generated;
asset.hash = processed.hash;
asset.cacheData = processed.cacheData;
asset.resolvePaths = processed.resolvePaths;

// Call the delegate to get implicit dependencies
let dependencies = processed.dependencies;
Expand Down
4 changes: 3 additions & 1 deletion packages/core/parcel-bundler/src/Pipeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class Pipeline {
generated: generatedMap,
error: error,
hash: asset.hash,
cacheData: asset.cacheData
cacheData: asset.cacheData,
resolvePaths: asset.resolvePaths
};
}

Expand Down Expand Up @@ -70,6 +71,7 @@ class Pipeline {
subAsset.contents = value;
subAsset.dependencies = asset.dependencies;
subAsset.cacheData = Object.assign(asset.cacheData, subAsset.cacheData);
subAsset.resolvePaths = asset.resolvePaths;

let processed = await this.processAsset(subAsset);
if (rendition.meta) {
Expand Down
60 changes: 58 additions & 2 deletions packages/core/parcel-bundler/src/Resolver.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const builtins = require('./builtins');
const nodeBuiltins = require('node-libs-browser');
const path = require('path');
const {isGlob} = require('./utils/glob');
const {isGlob, glob} = require('./utils/glob');
const fs = require('@parcel/fs');
const micromatch = require('micromatch');
const getModuleParts = require('./utils/getModuleParts');
Expand Down Expand Up @@ -29,7 +29,7 @@ class Resolver {
this.rootPackage = null;
}

async resolve(input, parent) {
async resolve(input, parent, resolvePaths) {
let filename = input;

// Check the cache first
Expand Down Expand Up @@ -66,6 +66,20 @@ class Resolver {
resolved = await this.loadRelative(module.filePath, extensions);
}

// Resolve the module in custom module path
if (!resolved) {
try {
resolved = await this.findCustomResolvePath(
filename,
parent,
resolvePaths,
extensions
);
} catch (err) {
// ignore
}
}

if (!resolved) {
let dir = parent ? path.dirname(parent) : process.cwd();
let err = new Error(`Cannot find module '${input}' from '${dir}'`);
Expand Down Expand Up @@ -202,6 +216,48 @@ class Resolver {
}
}

async findCustomResolvePath(filename, parent, paths, extensions) {
const dir = path.dirname(parent);

for (let [globPattern, resolvePaths] of Object.entries(paths)) {
const re = micromatch.makeRe(globPattern, {capture: true});
const matcher = re.exec(filename);
if (matcher) {
filename = matcher[1];
for (let resolvePath of resolvePaths) {
if (isGlob(resolvePath)) {
let globPath;
if (path.isAbsolute(resolvePath)) {
globPath = path.normalize(resolvePath);
} else {
globPath = path.normalize(path.join(dir, resolvePath));
}
const entries = glob.sync(globPath);
for (let entry of entries) {
for (let ext of extensions) {
const module = path.normalize(filename + ext);
if (entry.endsWith(module)) {
const pkg = await this.findPackage(path.dirname(entry));
return {path: entry, pkg};
}
}
}
} else {
for (let ext of extensions) {
const entry = path.normalize(
path.join(dir, resolvePath, filename + ext)
);
if (await fs.exists(entry)) {
const pkg = await this.findPackage(path.dirname(entry));
return {path: entry, pkg};
}
}
}
}
}
}
}

async loadNodeModules(module, extensions) {
try {
// If a module was specified as a module sub-path (e.g. some-module/some/path),
Expand Down
2 changes: 2 additions & 0 deletions packages/core/parcel-bundler/src/assets/TypeScriptAsset.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class TypeScriptAsset extends Asset {
);
}

this.resolvePaths = transpilerOptions.compilerOptions.paths;

return [
{
type: 'js',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.getMessage = () => './app/foo.ts';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.getMessage = () => './core/util/foo.ts';
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import app_foo from '@app/foo';
import core_util_foo from '@core/foo';
import src_foo from '@src/foo';

app_foo.getMessage();
core_util_foo.getMessage();
src_foo.getMessage();
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "resolve-paths",
"version": "1.0.0",
"main": "index.ts"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.getMessage = () => './src/foo.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["esnext"],
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"noEmit": true,
"baseUrl": ".",
"paths": {
"@app/*": ["./app/*"],
"@core/*": ["./core/**"],
"@src/*": ["./src"]
}
}
}
28 changes: 28 additions & 0 deletions packages/core/parcel-bundler/test/resolvePaths.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const assert = require('assert');
const Path = require('path');
const Bundler = require('../src/Bundler');

describe('typescript asset', () => {
it('should be resolved with tsconfig paths when bundled', async () => {
const filename = Path.normalize(
Path.join(__dirname, '/integration/resolve-paths/index.ts')
);

const options = {
outDir: Path.join(__dirname, './integration/resolve-paths/dist'),
outFile: 'index.js',
cache: false,
hmr: false
};

const bundler = new Bundler(filename, options);
const bundle = await bundler.bundle();

const loadedAssets = [...bundle.assets.values()].map(asset => asset.id);

assert.equal(loadedAssets.includes('index.ts'), true);
assert.equal(loadedAssets.includes('app/foo.ts'), true);
assert.equal(loadedAssets.includes('core/util/foo.ts'), true);
assert.equal(loadedAssets.includes('src/foo.ts'), true);
});
});

0 comments on commit f6b12ff

Please sign in to comment.