📜 ⬆️ ⬇️

Webpack in Visual Studio for large solutions

CPDV We have a solution of 51 projects. 10 of them use TypeScript. The amount of minimized JavaScript code is ~ 1 MB. The typeScript of some projects depends on the code of other projects. For many React components, global variables are used.


Together, this leads to long hours of debugging front-end code. To simplify our lives, we have implemented a Webpack. And on the way caught a rake.


TL; DR


  1. Install node 7 + npm
  2. Perform in the console npm i -g webpack typescript
  3. Install Webpack Task Runner
  4. Add webpack.config.js
    to the folder of the "main" project
  5. Add webpack.config.part.js
    to the folder of each dependent project

The most common problems that we have when working with TypeScript code are “inconsistent” inheritance and abundance of global variables. They appear with the default settings of the studio and a large size of the solution.


The problem is “inconsistent” inheritance.


The problem with inheritance occurs when the base class connects after the child. When the Uncaught TypeError: Cannot read property 'prototype' of undefined error falls in our application, this is most likely a problem with "inconsistent" inheritance.


I will give an example. At the start we wrote the code below.


 namespace Sandbox { export class Base { protected foo() { console.log('foo'); } } export class Derived extends Base { public baz() { this.foo(); console.log('baz'); } } } 

We want each class to be in a separate file, because we believe that this is more convenient. And the code from the listing above is divided into two files: base.ts and derived.ts .


 namespace Sandbox { export class Base { protected foo() { console.log('foo'); } } } 

 namespace Sandbox { export class Derived extends Base { public baz() { this.foo(); console.log('baz'); } } } 

The derived.ts file appeared, which implicitly depends on the base.ts file. Now the order of connecting these two files is important: if you connect derived.js and then base.js , you will get an error message.


In the default settings of the studio, the order in which the dependent scripts are connected is important.


The problem is global variables.


In order for the TypeScript code from different projects to use common code, you have to declare global variables.


For example, we wrote a useful function makeSandwich in the Utils namespace in the Administration project:


 namespace Utils { ... export function makeSandwich() { ... } } 

We get the following code in javascript:


 var Utils; (function (Utils) { function makeSandwich() { ... } Utils.makeSandwich = makeSandwich; })(Utils || (Utils = {})); 

Created global variable Utils . In order to call a function, you have to refer to a global variable.


By themselves, global variables are harmless, but misusing them leads to long debug hours. For example, you can overwrite or override them.


At studio settings "by default" global variables are created.


Decision


Both "inconsistent" inheritance and global variables are problems of solving dependencies. In the JavaScript world, dependencies resolve special tools: Webpack, Browserify, RequireJS, SystemJS, and others. I chose a Webpack, since I used to work with it.


In Visual Studio since version 13 appeared Task Runner. This is a tool that binds the task (task) to the time of the project life cycle: at the opening, on Clean, before the build or after the build. Extend Task Runner Studio Plugins.


To embed Webpack into a build studio, use Task Runner and Webpack Task Runner plugin. Working with them is easy. Create a file webpack.config.js in the project folder and hang "Watch - Development" to open the project. More in this article .


Each time you launch "Watch - Development", a watch is launched over the file system - a build is triggered for each change in the monitored files. Without additional settings, everything works fine if you have one project. If you have two or more projects, watch will be launched for each of them. We have 10 projects with TypeScript. 10 friends on my computer work 3 minutes on the build scripts. And this is when changing a single ts-file. Need to improve.


Our projects are arranged in such a way that there is a "main" project with a site framework and "dependent" projects with plug-ins.


I set up our build in such a way that when loading the "main" project, the task "Watch - Development" will be launched with the help of the Studio Task Runner. The basic settings are in webpack.config.js : loaders, tsconfig, plugins. Inside webpack.config.js code is also written that searches all files in the solution folder for webpack.config.part.js . Each webpack.config.part.js file contains build settings for a specific project: entry, tsconfig overrides, and so on. Usually, there is only an entry. Both the “core” and “dependent” projects contain the file webpack.config.part.js . Thus, for the build of scripts in all projects only one watch is used.


Setting up the build server is trivial: run webpack -p in the folder of the "main" project.


Another nuance - besides Webpack, the studio still builds our TypeScript. In TypeScript since version 2.0 in tsconfig.json, you can disable the build of files with the exclude directive with the pattern ./Scripts/* . Webpack will ignore this setting. But in TypeScript 2.1, the compiler must find at least one file for the build, otherwise the error will fall. I had to leave one empty file for sacrificing the studio.


results


And the inheritance and use of global variables has degenerated into import directives:


 import { Base } from '../../../../../BaseProject/Scripts/Base'; import * as Utils from '../../../../../Utils'; export class Derived extends Base { public baz() { this.foo(); Utils.makeSandwich(); console.log('baz'); } } 

Pay attention to the long relative paths. They are here on purpose to show that this happens. Use intermediate files with imports from other projects and “zakenapsulirovat” a ton of long relative paths.


When using one watch instead of several, the build accelerated from 3 minutes to a few seconds.


The product of the compilation will be one file containing all the imported files. Moreover, when running with production-settings, the file will be minimized. Learn more about how Webpack works at webpack.js.org .


It is not possible to rewrite all our code for the use of imports in one approach. But the method described in the article allows you to do this work in parts.


findings



Links



')

Source: https://habr.com/ru/post/319156/


All Articles