# Batch and partial compilation of multiple projects with Webpack

#### Requirement

There was a case where we wanted to compile JavaScript for each project and store the compiled files in each project directory. Since I was only exporting all projects to the directory, I looked at how to export to the directory by directory. I also looked at how to build only specific projects, not all projects, and the results are included in this article.

.
├── package.json
├── src
│   ├── common                # project-wide file
│   └── projects
│       ├── foo　　　　　　　　　# Single Project
│       ├── fuga              # Single Project
│       ├── hoge              # Single Project
│       └── pages             # Special Project
│           ├── pageOne　　　　# Projects related to special projects
│           ├── pageThree     # Projects related to special projects
│           └── pageTwo       # Projects related to special projects
└── webpack.config.js


Normally, you can compile a multi-page application by setting the following in output of webpack.config.js as follows (Reference).

module.exports = {
//...
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
};



## Compile the application in each directory

This time, instead of writing them all together in one directory, we want to write them out in each project directory.

│   └── projects
│       ├── foo
│       │   ├── app.js
│       │   ├── dist          # I'd like to keep track of them here.
│       ├── fuga
│       │   ├── app.js
│       │   └── dist          # I'd like to keep track of them here.
│       ├── hoge
│       │   ├── app.js
│       │   └── dist          # I'd like to keep track of them here.


So, it may be a little tricky to change the settings of the entry and output to make the
I changed the setting to allow exporting to multiple directories. This time, I created a folder named dist for each project, and wrote the compiled file into it. This is what it looks like.

module.exports = {
//...
entry : {
'./src/projects/path-to-project/dist/hashfilename.js': './src/projects/path-to-project/app.js',
},
output: {
path: __dirname,
filename: '[name]'
}
};


The output.path is the path to the destination directory, which in this case is the directory directly underneath the root, and the path to the destination including the file name. The [name] used in the output replaces the entry key** in the webpack’s definition of output.path. So, with the above configuration, you can have **. /src/projects/path-to-project/dist/hashfilename.js** will be in [name].

As an aside, if you want to remove the dist directory from the git management, you can add the following to .gitignore.

/**/dist/


## Set up a common library for the project

The classes you want to use commonly in each project can be used in the following settings.

module.exports = {
//...
resolve: {
module: [
path.resolve(__dirname, './src/common'),
];
}
};


If you do this, . /src/common becomes a namespace, for example, if you want to use a file in . /src/common/Common.js file in your project, for example, a import statement would have the following format

import Common from 'Common';


Also, for . /src/common/particle/flower.js, you can connect the subdirectories as they are.

import Common from 'particle/flower';


## Decide on a target to compile and build

If you want to build multiple projects, you can focus on a specific project if you want to build only one project or two projects. When you run npm run build, you pass the project name of the build target as an environment variable (env) to webpack.config.js. Here’s what it looks like.

npm run build -- --env.target="hoge"


This command has two meanings: --env.target="foo" is the part that passes the environment variable (env) to webpack.config.js, and --env.target="hoge" is the part that passes the environment variable (env) to webpack.config.js. Also, if you want webpack.config.js to receive the environment variables (env), you need to change the export to a function.
You can use this function at https://webpack.js.org/guides/environment-variables/

To use the env variable, you must convert module.exports to a function:

webpack --env.NODE_ENV=local --env.production --progress

const path = require('path');

module.exports = env => {
console.log('NODE_ENV: ', env.NODE_ENV); // 'local'
console.log('Production: ', env.production); // true

return {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
};


In my case, I added the target property to env so that if there is a project directory in target, only that project will be built. By the way, all project files are unified as app.js.

// NOTE: Use function in order to pass environment variables.
// @see https://webpack.js.org/guides/environment-variables/
module.exports = (env, {watch} ) => {
let entry = {};

if (env && env.target) {
// NOTE: Divide target string into array by comma.
const targetFiles = env.target.split(',').map(s => s.trim())

for (file of targetFiles) {
// NOTE: I'm creating an entry for each project here (omitted)
const filePath = './' + join(targetDir, 'app.js');
const anEntry = createEntry(filePath);
Object.assign(entry, anEntry);
}
} else {
// NOTE: All Entry Information
entry = createAllEntry();
}

return {
//...
entry: entry,
output: {
path: __dirname,
filename: '[name]'
},
}
})


Here’s one more thing about the npm run build -- -- --env.target="foo" after the build at runtime, it means that any variables after the double hyphen are passed to the runtime file as variables. For example, there is the following npm package

 {
script:
{
server: "node index.js"
}
}


The environment variable --port=8080 will be passed to index.js when the following command is executed.

npm run server -- --port=8080


This is equivalent to running the node command as usual.

node server.js --port=1337


So there’s a difference between the two variables that are passed to the npm command and the variables that are passed to the script.

## Conclusion

In this article, I investigated how to build multiple projects by specifying a directory for each project, and how to build only a part of a project. The partial build seems to be useful when you have a lot of projects to build, to reduce the build time. The partial builds are also applied when you add the watch option, which may be useful when you are developing a project.

The project I used for this verification is available on Gihub, so I hope this will be of some help to you.