Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Having nameCache controls #256

Open
levani132 opened this issue Jun 2, 2020 · 14 comments
Open

Having nameCache controls #256

levani132 opened this issue Jun 2, 2020 · 14 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@levani132
Copy link

levani132 commented Jun 2, 2020

  • Operating System: Windows
  • Node Version: 13.5.0
  • NPM Version: 6.13.4
  • webpack Version: 4.41.2
  • terser-webpack-plugin Version: 3.0.2

Feature Proposal

What about adding nameCache option? I haven't used it before, but as documentation suggests we should be able to tell terser to use js object (or it would be more correct to call it dictionary) to map names (as I guess variables, classes, functions) to predefined, new, minified names instead of just renaming them to alphabetically smallest, nonempty, available string.

To say it simply, I'm asking to bring this somehow possible in webpack plugin too:

var cacheFileName = "/tmp/cache.json";
var options = {
    mangle: {
        properties: true,
    },
    nameCache: JSON.parse(fs.readFileSync(cacheFileName, "utf8"))
};
fs.writeFileSync("part1.js", Terser.minify({
    "file1.js": fs.readFileSync("file1.js", "utf8"),
    "file2.js": fs.readFileSync("file2.js", "utf8")
}, options).code, "utf8");
fs.writeFileSync("part2.js", Terser.minify({
    "file3.js": fs.readFileSync("file3.js", "utf8"),
    "file4.js": fs.readFileSync("file4.js", "utf8")
}, options).code, "utf8");
fs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), "utf8");

And this code in my opinion also saves new names cache to same file too. I think this is impossible now in terser webpack plugin.

Feature Request: Add ability/option to bind json file as name cache.

Feature Use Case

<! -- problem -->

Easiest use case would be, I need to build application (currently in angular) which has more than two files bundled (let's assume 3). First and second files both have dependency on third.

Now if I build only first file, after minification first minified file will have for example console.log(thirdModule.thirdModuleVariable) transformed into console.log(thirdModule.a).

But if I only build second file or if I build whole project thirdModule's thirdModuleVariable may become b.

</!-- problem -->

What I want in the end is that in angular application I have appModule => [firstLazyModule, secondLazyModule, thirdLazyModule]. Now I will build whole app, then I will comment out other two modules and build only appModule => [firstLazyModule] (because building all three of them takes too long and I have only changed code in firstLazyModule, after building app with only one module, I will take generated module bundle and I will replace corresponding module file in the firstly generated directory with this new module bundle file.

This whole thing works if I don't use terser plugin, but doesn't work with terser because of the problem I have provided. If I'll have nameCache file in the project, each time I build app it will generate and use in next builds same minified variable names and replacing modules will still work.

I hope we can work this out. Thank you in advance.

@alexander-akait
Copy link
Member

alexander-akait commented Jun 2, 2020

You can't use parallel in this case, so less perf

@levani132
Copy link
Author

levani132 commented Jun 3, 2020

Yeah, but maybe for someone parallel is more useful, but for me (And I think and hope there are many like me) this will be huge benefit. I mean will it be problem to make this possible without affecting everything else? Just add a little, simple option please.

@alexander-akait
Copy link
Member

@levani132 Yes, it is possible to implement, but you should do choose parallel or nameCache. Agree it can be useful for small applications.

@levani132
Copy link
Author

Yes, we won't be able to use both. Though I hope in my desired build flow this won't cause too much performance issues. My project has like 30 modules and I will be able to build them independently, so basically, if the build time becomes 12 times slower with my 12 threads pc, it will become 30 times faster to build separate modules.

By the way I haven't yet tested it but I have my own fork in my work PC where I'm playing around with this option and if I succeed I will bring that fork here on github and create a PR.

@alexander-akait
Copy link
Member

@levani132 Yes, feel free to send a PR

@alexander-akait alexander-akait added enhancement New feature or request help wanted Extra attention is needed labels Jun 3, 2020
@alexander-akait
Copy link
Member

hm, nameCache already work, just set parallel: false, but webpack@4 adding wrapper to mangle top function/vars/etc impossible, but it is possible with webpack@5

@levani132
Copy link
Author

levani132 commented Jul 17, 2020

Yeah, I see, but I can't wait until webpack 5 will be finally released (Also I'm trying to use nameCache in angular, so I will have to wait for angular to add webpack 5). So I managed to do what I wanted to do in webpack 4, but there's a little problem, Angular also uses optimization flag which converts some variables. If I disable Angular optimizations I achieve what I want (having cached everything that is mangled) but bundle size increases about 2-3 times. So now I'm researching what angular's optimization flag does to somehow make it cache things too maybe. After I succeed I'll test the functionality and send PR here too.

@masx200
Copy link

masx200 commented Aug 23, 2022

const result = await minify({ [filename]: code }, terserOptions);

In order for parallel and nameCache to be used together, we can update nameCache every time we call terser's minify, and then save the nameCache to a file after the webpack is packaged, and everything will work fine the second time.

@masx200
Copy link

masx200 commented Aug 23, 2022

But this leads to the cost that the modified code may need to be packaged twice to work properly.

@masx200
Copy link

masx200 commented Aug 23, 2022

If you want namecache and parallel to be used together and you don't want to package twice after each change, you can only make namecache a concurrenthashmap.

@alexander-akait
Copy link
Member

@masx200 yeah, you can't use nameCache and parallel together currently, but thank you for openning an issue in terser repo

@icy0307
Copy link

icy0307 commented Feb 1, 2023

IMHO, opening an issue in the terser repo would not help.
First of all, isn't the result of build processing should be deterministic for long-time caching?
If we want to use concurrency here, race conditions must occur somehow. Even if we manage to make the namecache concurrency safe, which one gets to write the map and occupy some name first is still unpredictable. @masx200

it is possible to implement, but you should do choose parallel or nameCache. Agree it can be useful for small applications.

For big web apps, mangle properties could reduce the bundles' size magnificently, like what google compile closure does for Google Docs.
However, this requires all related files to be processed by Terser all at once, which requires us to turn off parallel.
It is also intolerable for big apps.

More build time vs Smaller bundles' size.

Avoid using a module bundler, as they usually will call Terser on each file individually, making it impossible to pass mangled objects between modules.

Is there any way, like utilizing the module graph to find out which bundles can be processed simultaneously without causing naming conflicts? @alexander-akait

@alexander-akait
Copy link
Member

I don't think we really can solve it here... Files are in different threads, something like salt on terser side can solve it - i.e. we can generate salt using path.relative(context, filepath) and generate salt for file, then terser will shift all names based on salt (it is theoretical idea), so it will work in parallel mode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

5 participants
@alexander-akait @icy0307 @levani132 @masx200 and others