0

I want to import a submodule from a ts file into my project. The problem is that the output file includes the entire imported file and not only the imported object.

I have an example.ts file with several exports:

export enum e1{a, b}
export enum e2{c, d}
export class exampleclass
{
    static f()
    {
        return 1;
    }
}

Update: I have another file - exampleUser.ts which imports parts from example.ts.

import {e2} from "./example";

export enum eu1{a, b}
export enum eu2{c, d}

I have a 3rd file - main.ts which imports parts from exampleUser.ts. When I use the following import

import {eu2} from "./exampleUser";

and transpile the project (using webpack) the bundled output contains un-used parts of code from exampleUser.ts and from example.ts.

tsconfig.json:

{
   "compilerOptions": {
       "target": "es3",   
       "module": "es6",
       "allowJs": true, 
       "checkJs": false,
       "sourceMap": true,
       "removeComments": true,
       "strict": true,
       "noImplicitAny": true,
       "strictNullChecks": true,
    }
}

package.json:

{
   "sideEffects": false
   "devDependencies": {
    "concurrently": "^3.6.0",
    "ts-loader": "^4.3.0",
    "typescript": "^2.8.3",
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3"
   },
}

webpack.prod.js:

{
   mode: 'production',
   module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
   },
   optimization: {
     minimize: true, // Control if the output is monified (and uglified) or not
     usedExports: true
  },
}

package-lock.json:

{
   "ts-loader": {
      "version": "4.3.0",
      "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-4.3.0.tgz",
      "integrity": "sha512-+zduqQJaeouVrGY3y6+nUG7+OE1+Q7slGCHsiQM/aITCEZ0og3GxrJVsnjM5QcWvOcu9C4VR5dP+egIyT+sNNg==",
      "dev": true,
      "requires": {
        "chalk": "2.4.1",
        "enhanced-resolve": "4.0.0",
        "loader-utils": "1.1.0",
        "micromatch": "3.1.10",
        "semver": "5.5.0"
      }
    }
}

Is it possible to import only the relevant code?

1 Answer 1

1

Things you asking about is a Tree shaking. Typescript does not do it out of the box. You use webpack which can do that. Please see how to set up it here Tree shaking

I guess it would be enough to set mode: 'production' and webpack will optimize your output

UPD:

After some discuss it was found out: with typescript's target lower than "es2015" class will be compiled to regular function. Functions could have side effect via closures, so it could be unsafe to remove "unused code" and webpack includes everything "just in case"

To tell webpack that function is safe to delete compiler could put #__PURE__ comment near the function but Typescript puts @class instead.

We can write simple webpack loader to replace @class to #__PURE__. It is a little dirty but workable solution.

module.exports = function(content) {
  return content.replace(/\/\*\* @class \*\//g, '\n /*#__PURE__*/ \n');
};

The repo with proposed loader

On my projects I prefer the following solution: typescript => ESNext javascript (ts-loader) => Es5 (babel-loader) Typescript here is for type-checking, while babel take care about es5

Sign up to request clarification or add additional context in comments.

14 Comments

I tried what you suggested and it didn't work. I have updated my question with what I have found
https://webpack.js.org/guides/tree-shaking/#conclusion > Ensure no compilers transform your ES2015 module syntax into CommonJS modules Tree shaking is a feature of Webpack and it can do it with import/export sources only
Are you sure your ts-loader or other loaders you use to compile typescript keeps module system as es2015?
I am no too familiar with the ts-loader and its options. I have added the ts-loader configuration in my code. How can I tell if it's changing the target code from es2015?
In my example, I see that the entire class (e.g. exampleclass) is included in the bundle (although it's not imported).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.