TypeScript classes and Webpack - javascript

Let say I have a typescript class with 10 methods and that the file export a new instance of the class as its default export. Then I have another file, like a React functional component, that import this class and call one method on the class.
How will this be optimized? Can Webpack/Babel extract the code for just the method used, or will it include the whole class and I will have a bunch of unused code?
Is it better to avoid classes and export each function instead?
My goal is to make the exported bundles smaller and also have Lighthouse complain less about unused JavaScript.

Most tree shaking tools (including Webpack) work by analysing the tree of ES6 imports and exports in order to tree shake unused exports.
Take the following example:
export class {
myfunc1() { /* do stuff */ }
myfunc2() { /* do stuff */ }
}
When tree shaking with Webpack, if myFunc2 is used somewhere, myFunc1 cannot be tree shaken even if it is not used.
But here, either function could be tree shaken if not used:
export myFunc1 = () => { /* Do stuff */}
export myFunc2 = () => { /* Do stuff */}
In this case it is better for tree shaking (with Webpack) to use functions grouped together in a file, rather than a class.

Related

What is a good practice to encapsulate multiple JavaScript files within 1 ES6 module?

Having a C# / C++ packaging structure in mind, how do I achieve to have JS-classes in individual files all imported as a single name space?
My currently working solution is to use an additional "package"-script file, which then encapsulates all classes. See the code below.
It seems as this includes a lot of overhead (updating the package-script-exports with every new class, importing this script in every new class).
ClassA.js:
import * as MyPackage from "../MyPackage.js";
export default class ClassA {/* some Class Code */}
export {
ClassA
};
MyPackage.js:
import ClassA from "./module/ClassA.js";
import ClassB from "./module/ClassB.js";
export {
ClassA,ClassB
}
script.js:
import * as MyPackage from "./MyPackage.js"
let a = new MyPackage.ClassA();
What would be a best practice for that?
My currently working solution is to use an additional "package"-script file, which then encapsulates all classes.
Yes, this is the best practice. The "package" script file is typically called index.js placed in the directory of the package, as that's what the folder path is resolved to when importing.
importing this script in every new class
No, you should not do that. It introduces a circular dependency. As long as your module doesn't depend on any of the other classes, it should not import anything. There is no "package declaration", the module is a standalone file with its own dependencies.
Notice also that you shouldn't export your class twice from the module, the default export is enough. So you'd use
// mypackage/classA.js:
export default class ClassA {
/* some Class Code */
}
// mypackage/index.js:
export { default as ClassA } from "./classA.js";
export { default as ClassB } from "./classB.js";
// your solution of importing, then exporting works as well.
// script.js:
import * as MyPackage from "./mypackage";
const a = new MyPackage.ClassA();
// or
import { ClassA } from "./mypackage";
const a = new ClassA();

How can I import type information for Flow with RequireJS-loaded modules?

I have a large web project that currently uses RequireJS for module loading in development and optimization for production. Before Flow, files look something like this:
define(function(require) {
const React = require('react');
class Foo extends React.Component {
// [...some component code]
}
return Foo;
});
I'm interested in adding Flow to my system. I've got it working, more or less, but I'm missing some of the key features because I can't convince Flow that my required modules are the actual modules.
Given the following code, I'd expect a type error, but it only works if I add import * as React from 'react' to the top of my module, allowing flow to recognize the React.Component type. But that isn't compatible with loading modules through RequireJS.
I've tried creating various definitions for define, but I don't know how to tell flow that the require object being passed as the function's argument is the "real" require.
Sample code:
// #flow
define(function(require) {
const React = require('react');
type Props = {
foo: string
}
type State = {
bar: string
}
class Foo extends React.Component<Props, State> {
someMethod(): void {
this.setState({
bar: 1 // should trigger a type error
});
}
// [...other component code]
}
return Foo
}
In my flow-typed file for RequireJS:
declare function define(module: ((require: string) => any) => any): void;
Flow only knows how to parse and follow types within CommonJS and ES6 module files. There are a few super hacky comment-based solutions in https://github.com/facebook/flow/issues/28, but at the end of the day it just wasn't designed for AMD, so you're essentially writing a piece of your app inside a comment in order to make Flow see your file as CommonJS instead of AMD.
I understand that AMD is important for your workflow, so it seems like drastic changes to your build process are probably a no-go? Given that, the only real option that comes to mind for me would be for your to change your scripts to be authored as ES6 modules, but then compiled to AMD modules to later be bundled. Babel could for instance do this using its AMD output support, then those AMD modules could be bundled up as usual.
It's definitely painful and a decent amount of work no matter what way you look at it. AMD is just not common in modern-day tooling, at least not as an authoring format.

How to disable Tree shaking in rollupjs

I am trying to bundle together several javascript files using RollUp.js but when I do, the classes that aren't used get removed. This process is called tree shaking and I want to disable it.
I have found this but it doesn't seem to have any effect.
// rollup.config.js
let configuration = {
output: {
format: 'es',
},
name: 'namename',
input: './main.js',
treeshake: false, // <-- disabling tree shaking?
};
export default configuration;
I added treeshake: false to the configuration, but it doesn't seem to have any effect. Is this supposed to be placed somewhere else?
Here are the files I am trying to roll up.
// Base.js
export default class Base {
aMethod() {
return "Hello";
}
}
// main.js
import Base from './Base.js';
So with this set up, I call rollup --config and it produces something empty. So clearly, tree shaking is happening and it is removing the Base class even though I imported it.
So far the only workaround I've found is to actually create an instance of the class, which is undesirable.
// main.js
import Base from './Base.js';
export default function () {
{
new Base();
}
}
My goal is to use the bundled javascript file with JSContext. It will take in the javascript as a string and then from there, I'd invoke methods as needed.
// suppose rollup.js produces a file called "product.js"
let s = String(contentsOfFile: "path/to/product.js")
let context = JSContext()!
context.evaluateScript(s)
context.evaluateScript("var b = new Base()")
context.evaluateScript("b.aMethod()")
But because of the tree shaking the Base class never gets placed in product.js
Is there a way to disable tree shaking?
I've included a sample project for this.
Your entry file — main.js — needs to export any classes or other values that need to be accessible to the outside world:
// main.js
import Base from './Base.js';
import SubB from './SubB.js';
import SubA from './SubA.js';
export { Base, SubA, SubB };

Using namespace spread over multiple module files in TypeScript

I've started work on a large-scale typescript project.
Right from the outset, I want to keep my files organized (this project will be split between lots of developers so order is very necessary).
I have been attempting to use modules / namespaces and splitting classes out into separate files for each one, with a folder holding the namespace.
The file structure is:
app.ts
\Classes
---- \Animals
---- ---- Mammals.ts
---- ---- Reptiles.ts
I then attempt to import all files in that namespace in app.ts using something like: import * as Animals from "./Classes/Animals"
As for the namespace files themselves, I have tried the following, with no success:
namespace Animals {
export class Mammals {
constructor() {
}
}
}
and also:
module Animals {
export class Reptiles {
constructor() {
}
}
}
Unfortunately, the path is never recognized (as it points to a folder and not a single file). Is this even possible? Having all my classes from a single namespace in one file will result in files which are thousands of lines long and for this project that is not maintainable.
I have also noticed that TypeScript 1.5 has support for tsconfig.json - however, having to add each file manually to the map is a sure-fire way of introducing issues when developers start adding classes.
NOTE: I'm using Visual Studio 2015, TypeScript 1.5 (I believe, not sure how to verify). I also have ES6 support turned on.
Use re-exporting to create an external module that groups and exposes types from other modules:
// Classes/Animals.ts
export * from '.\Animals\Mammals';
export * from '.\Animals\Reptiles';
Then import the types from the new module as usual:
// app.ts
import * as Animals from '.\Classes\Animals'
let dog: Animals.Dog;
let snake: Animals.Snake;
Or
// app.ts
import { Dog, Snake } from '.\Classes\Animals'
let dog: Dog;
let snake: Snake;
Found a way to achieve your goal but not with the namespace keyword.
The "Animals" classes, Animal.ts & Mammal.ts & Reptile.ts under namespace.
with index.ts for the barrel.
animals.ts for namespace grouping.
Sample Classes:
index.ts (as barrel)
animals.ts (for namespace grouping)
And here you go of the concept of the namespace.
If you have your own library and you want to export the multiple files like from namespace, you can do this:
// classes/animals/mammals.ts
export enum Mammals {
cow = 'cow',
goat = 'goat',
}
// classes/animals/reptiles.ts
export interface Reptile {
isOurOverlord: boolean;
}
export function isOurOverlord(specimen: Reptile) { ... }
// classes/animals/index.ts
import * as mammals from './mammals';
import * as reptiles from './reptiles';
export { mammals, reptiles };
// classes/index.ts
import * as animals from './animals';
export { animals };
// app.ts
import { animals } from './classes';
const reptile: animals.reptiles.Reptile = {
isOurOverlord: animals.reptiles.isOurOverlord(...),
}
edit: i.e. you don't need typescript's namespaces in order to use that super convenient syntax of animals.reptiles.Reptile for types and values animals.mammals.Mammals within the same "namespace".
Seems there is no way to do this using namespaces on their own (unless you want to use Module Augmentation and declare every new item to add separately); however, a namespace can be part of a class, which can be extended! This is the best alternative I can find:
CoreLibraryTypes.ts
abstract class Types { }
namespace Types {
export class TypeA { }
export class TypeB { }
export class TypeC { }
}
export { Types };
CoreTypesExtended.ts
import CoreLibraryTypes from "./CoreLibraryTypes";
abstract class Types extends CoreLibraryTypes { }
namespace Types {
export class TypeD { }
export class TypeE { }
export class TypeF { }
}
export { Types };
The downside, of course, is that only the import of the second module will have the new types added. The first module will remain as before. Ideally it would be nice to "update" a namespace of types with additional types (like from plugins), such that module augmentation was more naturally supported (instead of having to write it by hand), but I guess that will have to do until someone realizes augmentation of modules by manually declaring updated definitions is just a half-a$$ way to do what namespaces already do lol (including classes, as seen above, which can already use namespace merging as part of the class). ;)
Note: In the example above I used export { Types }; for a reason - this will allow others to augment my modules. Augmentation is not supported for default exports (unless that is desired - sort of seals it virtually).
External modules imply that you load modules file by file. Both AMD and CommonJS do not have such thing as namespace. You can use some kind of postprocessing to bundle files in one module.
The following defines an internal module:
module Animals {
export class Reptiles {
constructor() {
}
}
}
You shouldn't use import for it. Animals.Reptiles is visible anywhere. The only aim is to load scripts in the proper order (e.g. base classes before heritors). So you should list all files in ts.config or somewhere else. In my project I use bundles on folders and have a convention to add # to filenames of base classes.
Another solution is to use external modules: AMD (RequireJS) or CommonJS (Browserify). In that case remove upper level module from declaration. If one file contains only one type you can export it as a root:
class Reptiles {
constructor() {
}
}
export = Reptiles;
You can refer module by file path:
import Reptilies = require('..\Animals\Reptilies')
var reptile = new Reptile();
Or with new ES6 modules:
export class Reptiles {
constructor() {
}
}
import { Reptiles } from '..\Animals\Reptilies';

How do I use namespaces with TypeScript external modules?

I have some code:
baseTypes.ts
export namespace Living.Things {
export class Animal {
move() { /* ... */ }
}
export class Plant {
photosynthesize() { /* ... */ }
}
}
dog.ts
import b = require('./baseTypes');
export namespace Living.Things {
// Error, can't find name 'Animal', ??
export class Dog extends Animal {
woof() { }
}
}
tree.ts
// Error, can't use the same name twice, ??
import b = require('./baseTypes');
import b = require('./dogs');
namespace Living.Things {
// Why do I have to write b.Living.Things.Plant instead of b.Plant??
class Tree extends b.Living.Things.Plant {
}
}
This is all very confusing. I want to have a bunch of external modules all contribute types to the same namespace, Living.Things. It seems that this doesn't work at all -- I can't see Animal in dogs.ts. I have to write the full namespace name b.Living.Things.Plant in tree.ts. It doesn't work to combine multiple objects in the same namespace across file. How do I do this?
Candy Cup Analogy
Version 1: A cup for every candy
Let's say you wrote some code like this:
Mod1.ts
export namespace A {
export class Twix { ... }
}
Mod2.ts
export namespace A {
export class PeanutButterCup { ... }
}
Mod3.ts
export namespace A {
export class KitKat { ... }
}
You've created this setup:
Each module (sheet of paper) gets its own cup named A. This is useless - you're not actually organizing your candy here, you're just adding an additional step (taking it out of the cup) between you and the treats.
Version 2: One cup in the global scope
If you weren't using modules, you might write code like this (note the lack of export declarations):
global1.ts
namespace A {
export class Twix { ... }
}
global2.ts
namespace A {
export class PeanutButterCup { ... }
}
global3.ts
namespace A {
export class KitKat { ... }
}
This code creates a merged namespace A in the global scope:
This setup is useful, but doesn't apply in the case of modules (because modules don't pollute the global scope).
Version 3: Going cupless
Going back to the original example, the cups A, A, and A aren't doing you any favors. Instead, you could write the code as:
Mod1.ts
export class Twix { ... }
Mod2.ts
export class PeanutButterCup { ... }
Mod3.ts
export class KitKat { ... }
to create a picture that looks like this:
Much better!
Now, if you're still thinking about how much you really want to use namespace with your modules, read on...
These Aren't the Concepts You're Looking For
We need to go back to the origins of why namespaces exist in the first place and examine whether those reasons make sense for external modules.
Organization: Namespaces are handy for grouping together logically-related objects and types. For example, in C#, you're going to find all the collection types in System.Collections. By organizing our types into hierarchical namespaces, we provide a good "discovery" experience for users of those types.
Name Conflicts: Namespaces are important to avoid naming collisions. For example, you might have My.Application.Customer.AddForm and My.Application.Order.AddForm -- two types with the same name, but a different namespace. In a language where all identifiers exist in the same root scope and all assemblies load all types, it's critical to have everything be in a namespace.
Do those reasons make sense in external modules?
Organization: External modules are already present in a file system, necessarily. We have to resolve them by path and filename, so there's a logical organization scheme for us to use. We can have a /collections/generic/ folder with a list module in it.
Name Conflicts: This doesn't apply at all in external modules. Within a module, there's no plausible reason to have two objects with the same name. From the consumption side, the consumer of any given module gets to pick the name that they will use to refer to the module, so accidental naming conflicts are impossible.
Even if you don't believe that those reasons are adequately addressed by how modules work, the "solution" of trying to use namespaces in external modules doesn't even work.
Boxes in Boxes in Boxes
A story:
Your friend Bob calls you up. "I have a great new organization scheme in my house", he says, "come check it out!". Neat, let's go see what Bob has come up with.
You start in the kitchen and open up the pantry. There are 60 different boxes, each labelled "Pantry". You pick a box at random and open it. Inside is a single box labelled "Grains". You open up the "Grains" box and find a single box labelled "Pasta". You open the "Pasta" box and find a single box labelled "Penne". You open this box and find, as you expect, a bag of penne pasta.
Slightly confused, you pick up an adjacent box, also labelled "Pantry". Inside is a single box, again labelled "Grains". You open up the "Grains" box and, again, find a single box labelled "Pasta". You open the "Pasta" box and find a single box, this one is labelled "Rigatoni". You open this box and find... a bag of rigatoni pasta.
"It's great!" says Bob. "Everything is in a namespace!".
"But Bob..." you reply. "Your organization scheme is useless. You have to open up a bunch of boxes to get to anything, and it's not actually any more convenient to find anything than if you had just put everything in one box instead of three. In fact, since your pantry is already sorted shelf-by-shelf, you don't need the boxes at all. Why not just set the pasta on the shelf and pick it up when you need it?"
"You don't understand -- I need to make sure that no one else puts something that doesn't belong in the 'Pantry' namespace. And I've safely organized all my pasta into the Pantry.Grains.Pasta namespace so I can easily find it"
Bob is a very confused man.
Modules are Their Own Box
You've probably had something similar happen in real life: You order a few things on Amazon, and each item shows up in its own box, with a smaller box inside, with your item wrapped in its own packaging. Even if the interior boxes are similar, the shipments are not usefully "combined".
Going with the box analogy, the key observation is that external modules are their own box. It might be a very complex item with lots of functionality, but any given external module is its own box.
Guidance for External Modules
Now that we've figured out that we don't need to use 'namespaces', how should we organize our modules? Some guiding principles and examples follow.
Export as close to top-level as possible
If you're only exporting a single class or function, use export default:
MyClass.ts
export default class SomeType {
constructor() { ... }
}
MyFunc.ts
function getThing() { return 'thing'; }
export default getThing;
Consumption
import t from './MyClass';
import f from './MyFunc';
var x = new t();
console.log(f());
This is optimal for consumers. They can name your type whatever they want (t in this case) and don't have to do any extraneous dotting to find your objects.
If you're exporting multiple objects, put them all at top-level:
MyThings.ts
export class SomeType { ... }
export function someFunc() { ... }
Consumption
import * as m from './MyThings';
var x = new m.SomeType();
var y = m.someFunc();
If you're exporting a large number of things, only then should you use the module/namespace keyword:
MyLargeModule.ts
export namespace Animals {
export class Dog { ... }
export class Cat { ... }
}
export namespace Plants {
export class Tree { ... }
}
Consumption
import { Animals, Plants} from './MyLargeModule';
var x = new Animals.Dog();
Red Flags
All of the following are red flags for module structuring. Double-check that you're not trying to namespace your external modules if any of these apply to your files:
A file whose only top-level declaration is export module Foo { ... } (remove Foo and move everything 'up' a level)
A file that has a single export class or export function that isn't export default
Multiple files that have the same export module Foo { at top-level (don't think that these are going to combine into one Foo!)
Nothing wrong with Ryan's answer, but for people who came here looking for how to maintain a one-class-per-file structure while still using ES6 namespaces correctly please refer to this helpful resource from Microsoft.
One thing that's unclear to me after reading the doc is: how to import the entire (merged) module with a single import.
Edit
Circling back to update this answer. A few approaches to namespacing emerge in TS.
All module classes in one file.
export namespace Shapes {
export class Triangle {}
export class Square {}
}
Import files into namespace, and reassign
import { Triangle as _Triangle } from './triangle';
import { Square as _Square } from './square';
export namespace Shapes {
export const Triangle = _Triangle;
export const Square = _Square;
}
Barrels
// ./shapes/index.ts
export { Triangle } from './triangle';
export { Square } from './square';
// in importing file:
import * as Shapes from './shapes/index.ts';
// by node module convention, you can ignore '/index.ts':
import * as Shapes from './shapes';
let myTriangle = new Shapes.Triangle();
A final consideration. You could namespace each file
// triangle.ts
export namespace Shapes {
export class Triangle {}
}
// square.ts
export namespace Shapes {
export class Square {}
}
But as one imports two classes from the same namespace, TS will complain there's a duplicate identifier. The only solution as this time is to then alias the namespace.
import { Shapes } from './square';
import { Shapes as _Shapes } from './triangle';
// ugh
let myTriangle = new _Shapes.Shapes.Triangle();
This aliasing is absolutely abhorrent, so don't do it. You're better off with an approach above. Personally, I prefer the 'barrel'.
Try to organize by folder:
baseTypes.ts
export class Animal {
move() { /* ... */ }
}
export class Plant {
photosynthesize() { /* ... */ }
}
dog.ts
import b = require('./baseTypes');
export class Dog extends b.Animal {
woof() { }
}
tree.ts
import b = require('./baseTypes');
class Tree extends b.Plant {
}
LivingThings.ts
import dog = require('./dog')
import tree = require('./tree')
export = {
dog: dog,
tree: tree
}
main.ts
import LivingThings = require('./LivingThings');
console.log(LivingThings.Tree)
console.log(LivingThings.Dog)
The idea is that your module themselves shouldn't care / know they are participating in a namespace, but this exposes your API to the consumer in a compact, sensible way which is agnostic to which type of module system you are using for the project.
Try this namespaces module
namespaceModuleFile.ts
export namespace Bookname{
export class Snows{
name:any;
constructor(bookname){
console.log(bookname);
}
}
export class Adventure{
name:any;
constructor(bookname){
console.log(bookname);
}
}
}
export namespace TreeList{
export class MangoTree{
name:any;
constructor(treeName){
console.log(treeName);
}
}
export class GuvavaTree{
name:any;
constructor(treeName){
console.log(treeName);
}
}
}
bookTreeCombine.ts
---compilation part---
import {Bookname , TreeList} from './namespaceModule';
import b = require('./namespaceModule');
let BooknameLists = new Bookname.Adventure('Pirate treasure');
BooknameLists = new Bookname.Snows('ways to write a book');
const TreeLis = new TreeList.MangoTree('trees present in nature');
const TreeLists = new TreeList.GuvavaTree('trees are the celebraties');
Several of the questions/comments I've seen around this subject sound to me as if the person is using Namespace where they mean 'module alias'. As Ryan Cavanaugh mentioned in one of his comments you can have a 'Wrapper' module re-export several modules.
If you really want to import it all from the same module name/alias, combine a wrapper module with a paths mapping in your tsconfig.json.
Example:
./path/to/CompanyName.Products/Foo.ts
export class Foo {
...
}
./path/to/CompanyName.Products/Bar.ts
export class Bar {
...
}
./path/to/CompanyName.Products/index.ts
export { Foo } from './Foo';
export { Bar } from './Bar';
tsconfig.json
{
"compilerOptions": {
...
paths: {
...
"CompanyName.Products": ["./path/to/CompanyName.Products/index"],
...
}
...
}
...
}
main.ts
import { Foo, Bar } from 'CompanyName.Products'
Note: The module resolution in the output .js files will need to be handled somehow, such as with this https://github.com/tleunen/babel-plugin-module-resolver
Example .babelrc to handle the alias resolution:
{
"plugins": [
[ "module-resolver", {
"cwd": "babelrc",
"alias": {
"CompanyName.Products": "./path/to/typescript/build/output/CompanyName.Products/index.js"
}
}],
... other plugins ...
]
}
Small impovement of Albinofrenchy answer:
base.ts
export class Animal {
move() { /* ... */ }
}
export class Plant {
photosynthesize() { /* ... */ }
}
dog.ts
import * as b from './base';
export class Dog extends b.Animal {
woof() { }
}
things.ts
import { Dog } from './dog'
namespace things {
export const dog = Dog;
}
export = things;
main.ts
import * as things from './things';
console.log(things.dog);
OP I'm with you man.
again too, there is nothing wrong with that answer with 300+ up votes, but my opinion is:
what is wrong with putting classes into their cozy warm own files individually?
I mean this will make things looks much better right? (or someone just like a 1000 line file for all the models)
so then, if the first one will be achieved, we have to import import import... import just in each of the model files like man, srsly, a model file, a .d.ts file, why there are so many *s in there? it should just be simple, tidy, and that's it. Why I need imports there? why? C# got namespaces for a reason.
And by then, you are literally using "filenames.ts" as identifiers. As identifiers... Come on its 2017 now and we still do that? Ima go back to Mars and sleep for another 1000 years.
So sadly, my answer is: nop, you cannot make the "namespace" thing functional if you do not using all those imports or using those filenames as identifiers (which I think is really silly). Another option is: put all of those dependencies into a box called filenameasidentifier.ts and use
export namespace(or module) boxInBox {} .
wrap them so they wont try to access other classes with same name when they are just simply trying to get a reference from the class sit right on top of them.
You can use * as wrapper_var syntax to make all imported methods accessible under wrapper_var:
import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();
dog.ts
import b = require('./baseTypes');
export module Living.Things {
// Error, can't find name 'Animal', ??
// Solved: can find, if properly referenced; exporting modules is useless, anyhow
export class Dog extends b.Living.Things.Animal {
public woof(): void {
return;
}
}
}
tree.ts
// Error, can't use the same name twice, ??
// Solved: cannot declare let or const variable twice in same scope either: just use a different name
import b = require('./baseTypes');
import d = require('./dog');
module Living.Things {
// Why do I have to write b.Living.Things.Plant instead of b.Plant??
class Tree extends b.Living.Things.Plant {
}
}
The proper way to organize your code is to use separate directories in place of namespaces. Each class will be in it's own file, in it's respective namespace folder. index.ts will only re-export each file; no actual code should be in the index.ts file. Organizing your code like this makes it far easier to navigate, and is self-documenting based on directory structure.
// index.ts
import * as greeter from './greeter';
import * as somethingElse from './somethingElse';
export {greeter, somethingElse};
// greeter/index.ts
export * from './greetings.js';
...
// greeter/greetings.ts
export const helloWorld = "Hello World";
You would then use it as such:
import { greeter } from 'your-package'; //Import it like normal, be it from an NPM module or from a directory.
// You can also use the following syntax, if you prefer:
import * as package from 'your-package';
console.log(greeter.helloWorld);

Categories

Resources