├── assets
├── samples
│ └── GSoC 2020 Accepted Proposal.pdf
├── templates
│ └── webpack GSoC Proposal Template.pdf
└── examples
│ └── simple-plugin.js
├── docs
├── proposal-guidelines.md
├── development-setup.md
├── project-ideas.md
├── technical-guides
│ ├── plugin-system.md
│ └── testing.md
└── webpack-architecture.md
└── README.md
/assets/samples/GSoC 2020 Accepted Proposal.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/gsoc/main/assets/samples/GSoC 2020 Accepted Proposal.pdf
--------------------------------------------------------------------------------
/assets/templates/webpack GSoC Proposal Template.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack/gsoc/main/assets/templates/webpack GSoC Proposal Template.pdf
--------------------------------------------------------------------------------
/docs/proposal-guidelines.md:
--------------------------------------------------------------------------------
1 | # Writing a Strong GSoC Proposal
2 |
3 | A good Google Summer of Code proposal tells a clear story: what problem you'll solve, how you'll solve it, and why you're the right person to do it. This guide will help you write a proposal that stands out.
4 |
5 | ## What Makes a Good Proposal
6 |
7 | **Clear problem description** - Show you understand a real issue that webpack users face.
8 |
9 | **Thoughtful solution** - Demonstrate you've researched the problem and have a realistic approach.
10 |
11 | **Proven ability** - Your contributions to webpack prove you can work with the codebase.
12 |
13 | **Realistic timeline** - Break down the work into achievable milestones with buffer time.
14 |
15 | **Personal motivation** - Explain why this project matters to you and the webpack community.
16 |
17 | ## Before You Write
18 |
19 | ### Make Contributions First
20 |
21 | GSoC applications **require** at least one merged contribution to webpack. This isn't just a checkbox - it helps you understand how webpack works and proves you can contribute effectively.
22 |
23 | Start with these repositories:
24 | - [webpack/webpack](https://github.com/webpack/webpack) - Core functionality
25 | - [webpack/webpack-cli](https://github.com/webpack/webpack-cli) - Command line interface
26 | - [webpack/webpack.js.org](https://github.com/webpack/webpack.js.org) - Documentation
27 |
28 | Look for issues labeled `good first issue` or `help wanted`.
29 |
30 | ### Understand webpack Deeply
31 |
32 | Before proposing changes, make sure you understand:
33 |
34 | - How webpack's [compilation process](webpack-architecture.md) works
35 | - The [plugin system](technical-guides/plugin-system.md) and how extensions work
36 | - Current webpack [issues and pain points](https://github.com/webpack/webpack/issues)
37 | - What the community is discussing on [Discord](https://discord.gg/PebpZRPfJp)
38 |
39 | ### Study the Project Ideas
40 |
41 | Review our [project ideas list](project-ideas.md) for inspiration, but don't limit yourself to these suggestions. The best proposals often come from contributors who've identified problems through their own experience.
42 |
43 | ## Proposal Structure
44 |
45 | > **💡 Tip**: Use our [webpack GSoC Proposal Template](../assets/templates/webpack%20GSoC%20Proposal%20Template.pdf) as a starting point for your proposal structure.
46 |
47 | ### 1. Title and Problem (1-2 paragraphs)
48 |
49 | Start with a clear title and explain the specific problem you're solving:
50 | - What challenge do webpack users face?
51 | - Why is this important to the community?
52 | - How does this align with webpack's goals?
53 |
54 | ### 2. Your Solution (2-3 paragraphs)
55 |
56 | Describe your approach clearly:
57 | - What will you build?
58 | - How will it work technically?
59 | - Why is this the best approach?
60 |
61 | ### 3. Timeline (3-4 milestones)
62 |
63 | Break your 12-week project into clear phases:
64 | - **Weeks 1-3**: Research and design
65 | - **Weeks 4-6**: Core implementation
66 | - **Weeks 7-9**: Integration and testing
67 | - **Weeks 10-12**: Polish and documentation
68 |
69 | Include specific deliverables for each phase.
70 |
71 | ### 4. Your Background (1 paragraph)
72 |
73 | Show you can deliver:
74 | - Your webpack contributions so far
75 | - Relevant technical experience
76 | - Why this project interests you
77 |
78 | ### 5. Post-GSoC Commitment (1 paragraph)
79 |
80 | Explain how you'll maintain the feature after GSoC ends.
81 |
82 | ## Writing Tips
83 |
84 | **Be specific** - "Improve build performance by 25% for large projects" instead of "make webpack faster"
85 |
86 | **Show your work** - Link to your contributions and reference specific webpack issues
87 |
88 | **Write clearly** - Your reviewers are busy. Make it easy to understand your proposal
89 |
90 | **Stay focused** - A clear 3-page proposal beats a rambling 10-page one
91 |
92 | ## Common Mistakes to Avoid
93 |
94 | **Unrealistic scope** - GSoC is 12 weeks. Be honest about what's achievable.
95 |
96 | **No prior contributions** - Make meaningful contributions before applying.
97 |
98 | **Vague technical details** - Show you understand the implementation challenges.
99 |
100 | **Ignoring the community** - Engage with webpack developers and users.
101 |
102 | ## Evaluation Criteria
103 |
104 | Proposals are evaluated on:
105 | - **Technical merit** (40%) - Is the solution well-researched?
106 | - **Your capability** (30%) - Can you execute based on your contributions?
107 | - **Project value** (20%) - Will this help webpack users?
108 | - **Proposal quality** (10%) - Is it well-written and clear?
109 |
110 | ## Getting Help
111 |
112 | **Ask early** - Don't wait until deadline to ask questions
113 |
114 | **Share drafts** - Get feedback from mentors and community
115 |
116 | **Stay engaged** - Keep contributing while your proposal is reviewed
117 |
118 | ## Final Checklist
119 |
120 | Before submitting:
121 | - [ ] Clear problem statement with examples
122 | - [ ] Realistic 12-week timeline
123 | - [ ] Links to your webpack contributions
124 | - [ ] Evidence of community engagement
125 | - [ ] Professional writing and grammar
126 |
127 | ## Resources
128 |
129 | - [webpack GSoC Proposal Template](../assets/templates/webpack%20GSoC%20Proposal%20Template.pdf) - Official template to guide your proposal structure
130 | - [Past successful proposals](https://medium.com/webpack/gsoc-2020-with-webpack-6ad0a30bcaac)
131 | - [Google's student guide](https://google.github.io/gsocguides/student/)
132 | - [webpack Discord community](https://discord.gg/PebpZRPfJp)
133 |
134 | The best proposals come from contributors who understand webpack deeply through actual experience. Start contributing early, engage with the community, and let your proposal grow from genuine understanding of webpack's challenges and opportunities.
135 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
webpack GSoC Onboarding Guide 🎓
2 |
3 |
8 |
9 | Welcome to webpack's **Google Summer of Code (GSoC) onboarding repository**! This guide helps newcomers understand webpack, contribute effectively, and write successful GSoC proposals.
10 |
11 | > **webpack** is a powerful static module bundler for modern JavaScript applications used by millions of developers worldwide.
12 |
13 | ## 🚀 Quick Start
14 |
15 | ### GSoC Guides
16 | 1. **[Make Your First Contribution](#making-your-first-contribution)** - Required before applying
17 | 2. **[Understand webpack Architecture](docs/webpack-architecture.md)** - Learn how webpack works
18 | 3. **[Explore Project Ideas](docs/project-ideas.md)** - Find what interests you
19 | 4. **[Write Your Proposal](docs/proposal-guidelines.md)** - Craft a winning application
20 |
21 | ### webpack Guides
22 | 1. **[Development Setup](docs/development-setup.md)** - Get your environment ready
23 | 2. **[Contribution Guidelines](https://github.com/webpack/webpack/blob/main/CONTRIBUTING.md)** - webpack's official guide
24 | 3. **Technical Guides** - Deep dive into webpack internals:
25 | - [Plugin System](docs/technical-guides/plugin-system.md)
26 | - [Testing Guide](docs/technical-guides/testing.md)
27 |
28 | ## Making Your First Contribution
29 |
30 | > **Required for GSoC**: You must make at least one merged contribution before applying.
31 |
32 | ### Choose Your Repository
33 | - **[webpack/webpack](https://github.com/webpack/webpack)** - Core functionality
34 | - **[webpack/webpack-cli](https://github.com/webpack/webpack-cli)** - CLI improvements
35 | - **[webpack/webpack.js.org](https://github.com/webpack/webpack.js.org)** - Documentation
36 |
37 | ### Find Issues
38 | Look for `good first issue` or `help wanted` labels to get started.
39 |
40 | 📚 **Detailed guide**: [Contributing to webpack](https://github.com/webpack/webpack/blob/main/CONTRIBUTING.md)
41 |
42 | ## 📝 GSoC Application Process
43 |
44 | ### Requirements
45 | - ✅ At least one merged contribution to webpack
46 | - ✅ Clear project proposal with timeline
47 | - ✅ Active community engagement
48 | - ✅ Understanding of webpack architecture (or respective repositories related to any project idea)
49 |
50 | 📚 **Detailed guide**: [GSoC Proposal Guidelines](docs/proposal-guidelines.md)
51 |
52 | ## 💡 Project Ideas
53 |
54 | We have **8 focused project areas** across:
55 | - 🚀 Performance & Optimization
56 | - 🔧 Developer Experience
57 | - 📦 Modern JavaScript Support
58 |
59 | 📚 **View all ideas**: [Project Ideas](docs/project-ideas.md)
60 |
61 | ## 🤝 Community & Support
62 |
63 | - 💬 **Discord**: [webpack Discord Server](https://discord.gg/PebpZRPfJp)
64 | - 📧 **Discussions**: [GitHub Discussions](https://github.com/webpack/webpack/discussions)
65 | - 📰 **Blog**: [webpack Medium Publication](https://medium.com/webpack)
66 |
67 | ## 📚 Learning Resources
68 |
69 | ### Essential Reading
70 | - [webpack Documentation](https://webpack.js.org/)
71 | - [webpack Concepts](https://webpack.js.org/concepts/)
72 | - [crafting a good gsoc proposal](https://medium.com/@evenstensberg/writing-a-solid-google-summer-of-code-proposal-a200fc6e785b)
73 |
74 | ### Technical Guides
75 | - [webpack Plugin Architecture](docs/technical-guides/plugin-system.md)
76 | - [Testing webpack Code](docs/technical-guides/testing.md)
77 | - [Sample Plugin Code](assets/examples/simple-plugin.js) - Modern ES6+ plugin example
78 |
79 | ## 🏆 Past GSoC Success
80 |
81 | - **2018**: CLI Improvements & TypeScript Migration ([Vincent Chan](https://summerofcode.withgoogle.com/archive/2018/projects/5363095866179584))
82 |
83 | - **2018**: webpack-cli: Infrastructure and Automation Work ([Dhruvdutt Jadhav](https://summerofcode.withgoogle.com/archive/2018/projects/5998434809020416))
84 |
85 | - **2018**: Webpack dependencies with WebAssembly ([Jevan Chan](https://summerofcode.withgoogle.com/archive/2018/projects/5998434809020416))
86 |
87 | - **2019**: Output Reporter ([Devid Farinelli](https://summerofcode.withgoogle.com/archive/2019/projects/4597762119696384))
88 |
89 | - **2019**: Dev Server Refactor ([Kirill Nagaitsev](https://summerofcode.withgoogle.com/archive/2019/projects/4895317185527808))
90 |
91 | - **2020**: CLI Improvements & TypeScript Migration ([Nitin Kumar](https://medium.com/webpack/gsoc-2020-with-webpack-6ad0a30bcaac))
92 |
93 | - **2024**: Refactor tests on webpack-dev-server ([Mahdi Khashan](https://summerofcode.withgoogle.com/archive/2024/projects/vvPVCqzQc))
94 |
95 | - **2024**: Native css support ([zhaochenliu](https://summerofcode.withgoogle.com/archive/2024/projects/26o3C4CV))
96 |
97 | - **2024**: Webpack-cli: create-webpack-app package development ([Uzair Khan](https://summerofcode.withgoogle.com/archive/2024/projects/A71RRLYm))
98 |
99 | - **2025**: Enhancing Webpack with ESM Module Output ([Leo Hasegawa]([https://google.com](https://summerofcode.withgoogle.com/programs/2025/projects/HJMdVfAT)))
100 |
101 | ## 📞 Need Help?
102 |
103 | - **GSoC Questions**: Ask in [webpack discussions](https://github.com/webpack/webpack/discussions)
104 | - **Technical Help**: Join our [Discord server](https://discord.gg/PebpZRPfJp)
105 | - **Mentorship**: Reach out to the [webpack team](https://github.com/webpack/webpack?tab=readme-ov-file#current-project-members)
106 |
107 | ---
108 |
109 | ## 🏃♂️ Next Steps
110 |
111 | 1. **🔧 [Set up your development environment](docs/development-setup.md)**
112 | 2. **📖 [Learn webpack architecture](docs/webpack-architecture.md)**
113 | 3. **🎯 [Find your first contribution](https://github.com/webpack/webpack/blob/main/CONTRIBUTING.md)**
114 | 4. **💡 [Explore project ideas](docs/project-ideas.md)**
115 |
116 | ---
117 |
118 | *Made with ❤️ by the webpack team and community contributors*
119 |
120 | **Happy coding! 🎉**
121 |
--------------------------------------------------------------------------------
/assets/examples/simple-plugin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * BundleAnalyzerPlugin - A modern webpack plugin example
3 | *
4 | * This plugin demonstrates key webpack plugin concepts:
5 | * - Modern JavaScript syntax (ES6+ features)
6 | * - Proper hook usage and registration
7 | * - Asset processing and generation
8 | * - Option validation and defaults
9 | * - JSON report generation
10 | *
11 | * Usage:
12 | * const BundleAnalyzerPlugin = require('./simple-plugin');
13 | *
14 | * module.exports = {
15 | * plugins: [
16 | * new BundleAnalyzerPlugin({
17 | * outputFile: 'bundle-report.json',
18 | * includeModules: true
19 | * })
20 | * ]
21 | * };
22 | */
23 |
24 | class BundleAnalyzerPlugin {
25 | // Modern class field syntax for default options
26 | static defaultOptions = {
27 | outputFile: 'bundle-analysis.json',
28 | includeModules: true,
29 | includeAssets: true,
30 | generateSummary: true
31 | };
32 |
33 | constructor(options = {}) {
34 | // Merge user options with defaults using object spread
35 | this.options = { ...BundleAnalyzerPlugin.defaultOptions, ...options };
36 | }
37 |
38 | apply(compiler) {
39 | const pluginName = BundleAnalyzerPlugin.name;
40 |
41 | // Access webpack's utility classes from the compiler
42 | const { webpack } = compiler;
43 | const { Compilation } = webpack;
44 | const { RawSource } = webpack.sources;
45 |
46 | // Hook into the compilation to access assets and modules
47 | compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
48 |
49 | // Hook into the asset processing stage
50 | compilation.hooks.processAssets.tap(
51 | {
52 | name: pluginName,
53 | // Use the REPORT stage to ensure all other assets are processed first
54 | stage: Compilation.PROCESS_ASSETS_STAGE_REPORT
55 | },
56 | (assets) => {
57 | // Generate bundle analysis
58 | const analysis = this.analyzeBundle(compilation, assets);
59 |
60 | // Convert analysis to JSON
61 | const reportContent = JSON.stringify(analysis, null, 2);
62 |
63 | // Add the report as a compilation asset
64 | compilation.emitAsset(
65 | this.options.outputFile,
66 | new RawSource(reportContent)
67 | );
68 | }
69 | );
70 | });
71 | }
72 |
73 | analyzeBundle(compilation, assets) {
74 | const analysis = {
75 | timestamp: new Date().toISOString(),
76 | webpack: compilation.compiler.webpack.version
77 | };
78 |
79 | // Analyze assets if requested
80 | if (this.options.includeAssets) {
81 | analysis.assets = {};
82 |
83 | // Use Object.entries for modern iteration
84 | for (const [name, source] of Object.entries(assets)) {
85 | analysis.assets[name] = {
86 | size: source.size(),
87 | type: this.getAssetType(name)
88 | };
89 | }
90 | }
91 |
92 | // Analyze modules if requested
93 | if (this.options.includeModules) {
94 | analysis.modules = {};
95 |
96 | // Iterate over compilation modules
97 | for (const module of compilation.modules) {
98 | if (module.resource) {
99 | analysis.modules[module.resource] = {
100 | size: module.size(),
101 | type: this.getModuleType(module.resource),
102 | // Use spread operator to convert Set to Array
103 | chunks: [...module.chunksIterable].map(chunk => chunk.id)
104 | };
105 | }
106 | }
107 | }
108 |
109 | // Analyze chunks
110 | analysis.chunks = {};
111 | for (const chunk of compilation.chunks) {
112 | analysis.chunks[chunk.id] = {
113 | name: chunk.name,
114 | size: chunk.size(),
115 | modules: chunk.getNumberOfModules(),
116 | files: [...chunk.files] // Convert Set to Array
117 | };
118 | }
119 |
120 | // Generate summary if requested
121 | if (this.options.generateSummary) {
122 | analysis.summary = this.generateSummary(analysis);
123 | }
124 |
125 | return analysis;
126 | }
127 |
128 | generateSummary(analysis) {
129 | const summary = {
130 | totalAssets: 0,
131 | totalModules: 0,
132 | totalChunks: Object.keys(analysis.chunks).length,
133 | totalSize: 0
134 | };
135 |
136 | // Calculate totals using modern array methods
137 | if (analysis.assets) {
138 | const assetSizes = Object.values(analysis.assets).map(asset => asset.size);
139 | summary.totalAssets = Object.keys(analysis.assets).length;
140 | summary.totalSize = assetSizes.reduce((sum, size) => sum + size, 0);
141 | }
142 |
143 | if (analysis.modules) {
144 | summary.totalModules = Object.keys(analysis.modules).length;
145 | }
146 |
147 | return summary;
148 | }
149 |
150 | getAssetType(filename) {
151 | // Use optional chaining and nullish coalescing
152 | const ext = filename.split('.').pop()?.toLowerCase();
153 |
154 | // Modern Map-like object for type mapping
155 | const typeMap = {
156 | 'js': 'javascript',
157 | 'css': 'stylesheet',
158 | 'html': 'document',
159 | 'json': 'data',
160 | 'png': 'image',
161 | 'jpg': 'image',
162 | 'jpeg': 'image',
163 | 'gif': 'image',
164 | 'svg': 'image',
165 | 'woff': 'font',
166 | 'woff2': 'font',
167 | 'ttf': 'font',
168 | 'eot': 'font'
169 | };
170 |
171 | return typeMap[ext] ?? 'unknown'; // Use nullish coalescing
172 | }
173 |
174 | getModuleType(resource) {
175 | const ext = resource.split('.').pop()?.toLowerCase();
176 |
177 | const typeMap = {
178 | 'js': 'javascript',
179 | 'jsx': 'react',
180 | 'ts': 'typescript',
181 | 'tsx': 'typescript-react',
182 | 'css': 'stylesheet',
183 | 'scss': 'sass',
184 | 'sass': 'sass',
185 | 'less': 'less',
186 | 'json': 'data',
187 | 'vue': 'vue-component'
188 | };
189 |
190 | return typeMap[ext] ?? 'unknown';
191 | }
192 | }
193 |
194 | // Export using modern syntax
195 | module.exports = BundleAnalyzerPlugin;
196 |
197 | // Additional export for ES6 modules
198 | module.exports.BundleAnalyzerPlugin = BundleAnalyzerPlugin;
199 |
--------------------------------------------------------------------------------
/docs/development-setup.md:
--------------------------------------------------------------------------------
1 | # Getting Your Development Environment Ready
2 |
3 | Setting up your development environment for webpack contribution is straightforward. This guide focuses on getting you up and running quickly with the essential tools you need, using GitHub CLI for a streamlined GitHub workflow.
4 |
5 | ## Prerequisites
6 |
7 | Before diving in, make sure you have these tools installed:
8 |
9 | **Node.js (Latest LTS)** - webpack requires modern Node.js. Download the latest LTS version from [nodejs.org](https://nodejs.org/) or use [nvm](https://github.com/nvm-sh/nvm) to manage multiple versions.
10 |
11 | **GitHub CLI** - For seamless GitHub integration. See [GitHub CLI installation instructions](https://docs.github.com/en/github-cli/github-cli/about-github-cli#installing-github-cli).
12 |
13 | **A good code editor** - [VS Code](https://code.visualstudio.com/) works great with webpack projects and has excellent debugging support.
14 |
15 | Verify your setup:
16 | ```bash
17 | node --version # Should show the latest LTS version (currently v20.x.x or higher)
18 | npm --version # Should show 9.x.x or higher
19 | gh --version # Should show GitHub CLI version
20 | ```
21 |
22 | ### Authenticate with GitHub
23 |
24 | First-time setup requires authentication:
25 | ```bash
26 | gh auth login
27 | ```
28 |
29 | Follow the prompts to authenticate with your GitHub account. This will allow you to fork repositories, create pull requests, and manage issues directly from the command line.
30 |
31 | ## Setting Up webpack Core
32 |
33 | The fastest way to start contributing to webpack is to fork and clone using GitHub CLI:
34 |
35 | ```bash
36 | # Fork and clone webpack in one command
37 | gh repo fork webpack/webpack --clone=true
38 |
39 | # Navigate to the cloned repository
40 | cd webpack
41 |
42 | # Install dependencies
43 | npm install
44 | ```
45 |
46 | That's it! GitHub CLI automatically:
47 | - Forks the repository to your GitHub account
48 | - Clones your fork locally
49 | - Sets up proper remotes (`origin` for your fork, `upstream` for the original)
50 |
51 | ### Verify Your Setup
52 |
53 | Run a simple test to make sure everything works:
54 |
55 | ```bash
56 | npm test -- --testNamePattern="simple"
57 | ```
58 |
59 | If this passes, you're ready to start making changes and contributing.
60 |
61 | ## Basic Development Workflow
62 |
63 | Here's the streamlined workflow using GitHub CLI:
64 |
65 | **1. Stay current with upstream changes:**
66 | ```bash
67 | gh repo sync webpack/{repo} # Sync your fork with upstream
68 | ```
69 |
70 | **2. Create a branch for your work:**
71 | ```bash
72 | git switch -c fix/my-improvement
73 | ```
74 |
75 | **3. Make your changes and test them:**
76 | ```bash
77 | npm test # Run relevant tests
78 | ```
79 |
80 | **4. Commit, push, and create a pull request:**
81 | ```bash
82 | git add .
83 | git commit -m "fix: improve error message clarity"
84 | git push origin fix/my-improvement
85 |
86 | # Create pull request directly from the command line
87 | gh pr create --title "fix: improve error message clarity" --body "This PR improves error message clarity by..."
88 | ```
89 |
90 | The GitHub CLI will open your browser to complete the pull request if needed, or you can add more details using command flags.
91 |
92 | ## Running Tests
93 |
94 | webpack has different types of tests for different purposes:
95 |
96 | ```bash
97 | # Run all tests (this takes a while)
98 | npm test
99 |
100 | # Run specific test categories
101 | npm run test:unit # Fast unit tests
102 | npm run test:integration # Integration tests with real webpack configs
103 | ```
104 |
105 | When working on a specific feature, run only the tests related to your changes to get faster feedback.
106 |
107 |
108 |
109 | ## Debugging Your Changes
110 |
111 | ### Using Node.js Debugger
112 |
113 | To debug webpack compilation:
114 |
115 | ```bash
116 | # Debug a specific webpack build
117 | node --inspect-brk ./bin/webpack.js --config your-test-config.js
118 | ```
119 |
120 | Then open Chrome and go to `chrome://inspect` to connect to the debugger.
121 |
122 | ### Using VS Code Debugging
123 |
124 | VS Code can debug webpack directly. Create `.vscode/launch.json`:
125 |
126 | ```json
127 | {
128 | "version": "0.2.0",
129 | "configurations": [
130 | {
131 | "name": "Debug webpack",
132 | "type": "node",
133 | "request": "launch",
134 | "program": "${workspaceFolder}/bin/webpack.js",
135 | "args": ["--config", "webpack.config.js"],
136 | "console": "integratedTerminal"
137 | }
138 | ]
139 | }
140 | ```
141 |
142 | Now you can set breakpoints and debug webpack builds directly in VS Code.
143 |
144 | ### Analyzing Bundle Output
145 |
146 | To understand what webpack generates:
147 |
148 | ```bash
149 | # Generate detailed build statistics
150 | webpack --profile --json > stats.json
151 |
152 | # Analyze with webpack-bundle-analyzer
153 | npx webpack-bundle-analyzer stats.json
154 | ```
155 |
156 | This helps when working on optimization features or debugging bundle issues.
157 |
158 | ## Code Quality Tools
159 |
160 | webpack uses several tools to maintain code quality:
161 |
162 | ```bash
163 | # Check code formatting
164 | npm run lint:code
165 |
166 | # Fix formatting issues automatically
167 | npm run fix
168 | ```
169 |
170 | These checks run automatically in CI, so run them before submitting pull requests to catch issues early.
171 |
172 | ## Common Setup Issues
173 |
174 | **"Cannot find module" errors** - Usually means you need to run `npm install` or `npm run build`
175 |
176 | **Test failures** - Make sure you're on the latest main branch and have run `npm install` recently
177 |
178 | **Memory issues** - Increase Node.js memory limit: `export NODE_OPTIONS="--max-old-space-size=8192"`
179 |
180 | **Permission errors on macOS/Linux** - Fix npm permissions: `sudo chown -R $(whoami) ~/.npm`
181 |
182 | **GitHub CLI authentication issues** - Re-run `gh auth login` and ensure you have proper repository permissions
183 |
184 | ## Working with webpack Configurations
185 |
186 | When testing your changes, create simple webpack configurations in a test directory:
187 |
188 | ```javascript
189 | // test-config.js
190 | module.exports = {
191 | mode: 'development',
192 | entry: './test-entry.js',
193 | output: {
194 | filename: 'bundle.js',
195 | path: __dirname + '/dist'
196 | }
197 | // Add your plugin or configuration changes here
198 | };
199 | ```
200 |
--------------------------------------------------------------------------------
/docs/project-ideas.md:
--------------------------------------------------------------------------------
1 | # webpack GSoC Project Ideas
2 |
3 | This document outlines key project ideas for Google Summer of Code with webpack. These projects represent high-impact opportunities to improve webpack for millions of developers worldwide.
4 |
5 | > **Note**: These are carefully selected suggestions based on webpack's current priorities. You're also welcome to propose your own ideas that align with webpack's goals and community needs.
6 |
7 | ## 🎯 How to Choose a Project
8 |
9 | **Match your skills** with project requirements and **consider your interests** - passion drives success. Each project should fit the GSoC timeline (12 weeks) and have clear deliverables.
10 |
11 | **Before proposing**: Make contributions to webpack, engage with the community, and deeply understand the problem you want to solve.
12 |
13 | ## 🚀 Performance & Optimization
14 |
15 | ### Enhanced Bundle Analysis and Visualization
16 |
17 | **Difficulty**: Medium | **Skills**: JavaScript, Data Visualization, Performance Analysis
18 |
19 | **The Problem**: webpack-bundle-analyzer is widely used but lacks advanced analysis capabilities. Developers need better insights into bundle composition and optimization opportunities.
20 |
21 | **Your Solution Could Include**:
22 | - Advanced bundle analysis algorithms for detecting duplicates and inefficiencies
23 | - Interactive dependency graph visualizations
24 | - Automated recommendations for optimization opportunities
25 | - Performance impact prediction for different bundling strategies
26 |
27 | **Impact**: Help developers reduce bundle sizes and optimize application performance.
28 |
29 | ---
30 |
31 | ### Build Performance Profiler
32 |
33 | **Difficulty**: Medium-Hard | **Skills**: Node.js, Performance Analysis, CLI Tools
34 |
35 | **The Problem**: Large webpack builds can be slow, but developers lack detailed insights into where time is spent during compilation.
36 |
37 | **Your Solution Could Include**:
38 | - Comprehensive build performance profiler with phase-by-phase timing
39 | - Memory usage tracking and leak detection
40 | - Automated optimization recommendations
41 | - Integration with existing build tools and CI systems
42 |
43 | **Impact**: Significantly improve webpack build times for large applications.
44 |
45 | ---
46 |
47 | ### Advanced Tree Shaking
48 |
49 | **Difficulty**: Hard | **Skills**: JavaScript, AST Analysis, Module Systems
50 |
51 | **The Problem**: webpack's tree shaking could eliminate more unused code, especially in complex scenarios like method chaining and dynamic imports.
52 |
53 | **Your Solution Could Include**:
54 | - Enhanced detection of unused code patterns
55 | - Improved side-effect analysis for complex modules
56 | - Cross-module dead code elimination
57 | - Better support for modern ECMAScript features
58 |
59 | **Impact**: Reduce bundle sizes by eliminating more unused code automatically.
60 |
61 | ---
62 |
63 | ## 🔧 Developer Experience
64 |
65 | ### Better Error Messages and Debugging
66 |
67 | **Difficulty**: Medium | **Skills**: JavaScript, CLI Design, Error Handling
68 |
69 | **The Problem**: webpack's error messages can be confusing, especially for beginners. Better error reporting would improve the developer experience significantly.
70 |
71 | **Your Solution Could Include**:
72 | - Clear, actionable error messages with context
73 | - Interactive error resolution with suggested fixes
74 | - Educational explanations linked to documentation
75 | - Better stack traces and debugging information
76 |
77 | **Impact**: Make webpack more accessible to new developers and reduce debugging time.
78 |
79 | ---
80 |
81 | ### Hot Module Replacement Enhancements
82 |
83 | **Difficulty**: Medium-Hard | **Skills**: JavaScript, WebSockets, Module Systems
84 |
85 | **The Problem**: Hot Module Replacement (HMR) can be unreliable in complex applications, leading to full page reloads that slow development.
86 |
87 | **Your Solution Could Include**:
88 | - Improved HMR reliability and error recovery
89 | - Support for more module types and frameworks
90 | - Better debugging tools for HMR issues
91 | - Intelligent fallback strategies
92 |
93 | **Impact**: Faster development cycles with more reliable hot reloading.
94 |
95 | ---
96 |
97 | ### Interactive Configuration Assistant
98 |
99 | **Difficulty**: Medium | **Skills**: JavaScript, CLI Tools, Configuration Management
100 |
101 | **The Problem**: webpack configuration can be overwhelming for newcomers, creating a barrier to adoption.
102 |
103 | **Your Solution Could Include**:
104 | - Interactive configuration wizard with smart defaults
105 | - Best practice recommendations based on project type
106 | - Configuration validation with helpful suggestions
107 | - Migration tools for webpack updates
108 |
109 | **Impact**: Lower the entry barrier for new webpack users.
110 |
111 | ---
112 |
113 | ## 📦 Modern JavaScript Support
114 |
115 | ### Enhanced ES Module Support
116 |
117 | **Difficulty**: Medium-Hard | **Skills**: JavaScript, Module Systems, Node.js
118 |
119 | **The Problem**: As the JavaScript ecosystem adopts ES modules, webpack needs better support for modern module patterns and Node.js interoperability.
120 |
121 | **Your Solution Could Include**:
122 | - Improved ES module and CommonJS interoperability
123 | - Better support for dynamic imports and top-level await
124 | - Enhanced module resolution for ES modules
125 | - Node.js ES module compatibility improvements
126 |
127 | **Impact**: Better support for modern JavaScript applications and libraries.
128 |
129 | ---
130 |
131 | ### Modern Web Platform Integration
132 |
133 | **Difficulty**: Medium | **Skills**: JavaScript, Web APIs, Browser Technologies
134 |
135 | **The Problem**: webpack should better support modern web platform features like Web Components, Import Maps, and Progressive Web App capabilities.
136 |
137 | **Your Solution Could Include**:
138 | - Native Web Components support and optimization
139 | - Import Maps integration for better module loading
140 | - Enhanced Service Worker and PWA build capabilities
141 | - Integration with modern browser APIs
142 |
143 | **Impact**: Enable developers to build modern web applications more easily.
144 |
145 | ---
146 |
147 | ## 🎓 Getting Started
148 |
149 | ### Choose Your Project
150 |
151 | 1. **Study the problem area** - Use webpack in real projects to understand the challenges
152 | 2. **Make related contributions** - Show you can work with the relevant code
153 | 3. **Engage with mentors** - Discuss your ideas with webpack maintainers
154 | 4. **Create a detailed proposal** - Follow our [proposal guidelines](proposal-guidelines.md)
155 |
156 | ### Success Factors
157 |
158 | **Strong technical understanding** - Show you've researched the problem deeply
159 |
160 | **Realistic scope** - Break down the work into achievable 12-week milestones
161 |
162 | **Community engagement** - Participate in webpack discussions and contribute regularly
163 |
164 | **Clear impact** - Explain how your project will help webpack users
165 |
166 | ### Resources
167 |
168 | - [webpack Architecture Guide](webpack-architecture.md) - Understand how webpack works
169 | - [Plugin System Guide](technical-guides/plugin-system.md) - Learn webpack's extension model
170 | - [Contributing Guidelines](https://github.com/webpack/webpack/blob/main/CONTRIBUTING.md) - webpack's official guide
171 | - [webpack Discord Community](https://discord.gg/PebpZRPfJp) - Connect with developers
172 |
173 | ---
174 |
175 | *Remember: The best GSoC projects come from contributors who have used webpack extensively and identified real problems through their own experience. Start using webpack, contribute to the codebase, and let your project idea grow from genuine understanding of the challenges developers face.*
176 |
--------------------------------------------------------------------------------
/docs/technical-guides/plugin-system.md:
--------------------------------------------------------------------------------
1 | # Understanding webpack's Plugin System
2 |
3 | webpack's plugin system is the heart of its extensibility. Built on [Tapable](https://github.com/webpack/tapable), a sophisticated event system, plugins allow you to hook into every stage of the compilation process and extend webpack's capabilities.
4 |
5 | Think of webpack's compilation as a well-orchestrated symphony, where plugins act as conductors who can influence the performance at specific moments. Whether you want to optimize bundles, generate additional files, or modify the build process, plugins are your gateway to webpack's internals.
6 |
7 | ## How the Plugin System Works
8 |
9 | At its core, webpack's plugin system follows the [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern). webpack emits events (called "hooks") at various stages of compilation, and plugins "tap" into these hooks to execute custom logic.
10 |
11 | ```mermaid
12 | graph TD
13 | A[webpack Compilation Starts] --> B[Initialize Plugins]
14 | B --> C[beforeRun Hook]
15 | C --> D[run Hook]
16 | D --> E[compilation Hook]
17 | E --> F[emit Hook]
18 | F --> G[done Hook]
19 |
20 | B -.-> H[Plugin 1 taps hooks]
21 | B -.-> I[Plugin 2 taps hooks]
22 | B -.-> J[Plugin N taps hooks]
23 |
24 | H --> K[Custom Logic]
25 | I --> L[Custom Logic]
26 | J --> M[Custom Logic]
27 | ```
28 |
29 | The beauty of this system lies in its predictability. webpack guarantees that hooks fire in a specific order, allowing plugins to work together harmoniously.
30 |
31 | ## Tapable: The Event System
32 |
33 | webpack uses [Tapable](https://github.com/webpack/tapable) to manage its hook system. Tapable provides different types of hooks for different execution patterns:
34 |
35 | **Synchronous hooks** execute plugins one after another, while **asynchronous hooks** can wait for promises or callbacks. Some hooks allow plugins to modify data (waterfall hooks), while others can short-circuit execution (bail hooks).
36 |
37 | For a complete understanding of hook types, study the [Tapable documentation](https://github.com/webpack/tapable#hook-types) and examine how webpack uses them in practice.
38 |
39 | ## The Plugin Architecture
40 |
41 | Every webpack plugin follows a simple contract: it must have an `apply` method that receives the compiler instance. This method is your plugin's entry point where you register your event listeners.
42 |
43 | Let's examine how real webpack plugins implement this pattern by looking at some core examples:
44 |
45 | **Simple synchronous plugin**: [DefinePlugin](https://github.com/webpack/webpack/blob/main/lib/DefinePlugin.js) replaces variables in your code at build time.
46 |
47 | **Complex asynchronous plugin**: [HtmlWebpackPlugin](https://github.com/jantimon/html-webpack-plugin/blob/main/lib/html-webpack-plugin.js) generates HTML files and injects script tags.
48 |
49 | **Asset processing plugin**: [MiniCssExtractPlugin](https://github.com/webpack/mini-css-extract-plugin) extracts CSS into separate files.
50 |
51 | ## Learning from Examples
52 |
53 | To understand plugin development in practice, study the modern plugin example in our [examples directory](../../assets/examples/simple-plugin.js). This demonstrates:
54 |
55 | - Modern ES6+ JavaScript syntax
56 | - Proper hook registration and usage
57 | - Asset processing and generation
58 | - Option validation and defaults
59 | - Real-world plugin patterns
60 |
61 | The example shows how to build a bundle analyzer plugin that generates detailed reports about your webpack builds, following all current best practices.
62 |
63 | ## webpack's Core Components
64 |
65 | Understanding webpack's main components helps you choose the right hooks and write effective plugins:
66 |
67 | **[Compiler](https://github.com/webpack/webpack/blob/main/lib/Compiler.js)** manages the overall build lifecycle. It's where you'll find hooks like `beforeRun`, `run`, `compilation`, and `done`. Think of it as webpack's central nervous system.
68 |
69 | **[Compilation](https://github.com/webpack/webpack/blob/main/lib/Compilation.js)** represents a single build with specific files and settings. Its hooks like `buildModule`, `seal`, and `processAssets` let you interact with individual modules and assets.
70 |
71 | **[ModuleGraph](https://github.com/webpack/webpack/blob/main/lib/ModuleGraph.js)** tracks dependencies between modules, enabling optimizations like tree shaking and code splitting.
72 |
73 | ## Essential Hook References
74 |
75 | Rather than memorizing hooks, familiarize yourself with webpack's comprehensive documentation:
76 |
77 | - [Compiler Hooks API](https://webpack.js.org/api/compiler-hooks/) lists all compiler-level hooks with examples
78 | - [Compilation Hooks API](https://webpack.js.org/api/compilation-hooks/) covers compilation-specific hooks
79 | - [Plugin API Guide](https://webpack.js.org/contribute/writing-a-plugin/) from webpack's official docs
80 |
81 | For deeper understanding, examine how webpack itself uses these hooks in its [core plugins directory](https://github.com/webpack/webpack/tree/main/lib).
82 |
83 | ## Performance Considerations
84 |
85 | When writing plugins, keep performance in mind. webpack processes thousands of modules in large applications, so inefficient plugins can significantly impact build times.
86 |
87 | **Avoid expensive operations** in frequently called hooks like `buildModule`. If you must perform heavy computations, consider [memoization](https://en.wikipedia.org/wiki/Memoization) or [lazy evaluation](https://en.wikipedia.org/wiki/Lazy_evaluation).
88 |
89 | **Use appropriate hook types**. Don't use asynchronous hooks when synchronous ones suffice, as async hooks have additional overhead.
90 |
91 | Study webpack's [performance optimization techniques](https://webpack.js.org/guides/build-performance/) and apply similar principles to your plugins.
92 |
93 | ## Testing Your Plugins
94 |
95 | webpack's own test suite provides excellent examples of plugin testing patterns. Examine the [plugin tests directory](https://github.com/webpack/webpack/tree/main/test/plugins) to see how webpack tests its built-in plugins.
96 |
97 | The key insight from webpack's approach is to test plugins by running actual webpack compilations and examining the results, rather than mocking extensively.
98 |
99 | ## Learning from the Ecosystem
100 |
101 | The webpack ecosystem contains hundreds of plugins solving real-world problems. Study successful plugins to understand common patterns:
102 |
103 | The webpack ecosystem contains hundreds of plugins solving real-world problems. Study successful plugins to understand common patterns:
104 |
105 | **[awesome-webpack](https://github.com/webpack-contrib/awesome-webpack)** curates community plugins and resources.
106 |
107 | When studying existing plugins, pay attention to how they handle errors, validate options using [schema-utils](https://github.com/webpack/schema-utils), and interact with other plugins.
108 |
109 | ## Common Plugin Patterns
110 |
111 | **Asset transformation**: Plugins often process assets during the `processAssets` hook. Study [TerserPlugin](https://github.com/webpack/terser-webpack-plugin) for JavaScript minification patterns.
112 |
113 | **Code analysis**: Many plugins analyze the module graph to make optimizations. [webpack-bundle-analyzer](https://github.com/webpack/webpack-bundle-analyzer) provides excellent examples.
114 |
115 | **File generation**: Plugins frequently generate additional files. [HtmlWebpackPlugin](https://github.com/jantimon/html-webpack-plugin) demonstrates sophisticated template processing.
116 |
117 | ## Error Handling
118 |
119 | webpack provides [WebpackError](https://github.com/webpack/webpack/blob/main/lib/WebpackError.js) for consistent error reporting. Use this class for plugin-specific errors to ensure they display properly in webpack's output.
120 |
121 | Always handle errors gracefully in asynchronous hooks, and provide meaningful error messages that help developers debug issues.
122 |
123 | ## Next Steps
124 |
125 | Start by studying webpack's [plugin writing guide](https://webpack.js.org/contribute/writing-a-plugin/) and examining the source code of plugins that interest you. Create simple plugins to understand the compilation lifecycle, then gradually tackle more complex scenarios.
126 |
127 | The webpack plugin system is powerful but approachable once you understand its patterns. Every webpack feature you use daily—from code splitting to asset optimization—is implemented through this same plugin system you're learning to master.
128 |
--------------------------------------------------------------------------------
/docs/webpack-architecture.md:
--------------------------------------------------------------------------------
1 | # webpack Architecture Deep Dive
2 |
3 | Understanding webpack's internal architecture is essential for effective contribution. This guide explores how webpack processes your code from entry to output, the key components involved, and how they work together to create optimized bundles.
4 |
5 | webpack is fundamentally a **static module bundler**. It analyzes your project's dependency graph starting from entry points and generates optimized bundles containing all necessary code.
6 |
7 | ## The Build Process Flow
8 |
9 | webpack's compilation follows a predictable sequence of phases, each with specific responsibilities:
10 |
11 | ```mermaid
12 | graph TD
13 | A[Entry Points] --> B[Module Resolution]
14 | B --> C[Module Loading & Parsing]
15 | C --> D[Dependency Graph Building]
16 | D --> E[Module Processing & Transformation]
17 | E --> F[Optimization Phase]
18 | F --> G[Chunk Generation]
19 | G --> H[Asset Generation]
20 | H --> I[Output Files]
21 |
22 | C -.-> J[Loaders Transform Files]
23 | E -.-> K[Plugins Process Modules]
24 | F -.-> L[Tree Shaking & Minification]
25 | G -.-> M[Code Splitting]
26 | ```
27 |
28 | This flow happens every time you run webpack, whether in development or production mode. Understanding this sequence helps you know where to hook in with plugins or loaders.
29 |
30 | ### Initialization Phase
31 |
32 | webpack starts by parsing your configuration and creating the main [Compiler](https://github.com/webpack/webpack/blob/main/lib/Compiler.js) instance. This compiler acts as webpack's central nervous system, orchestrating the entire build process.
33 |
34 | During initialization, webpack also sets up its plugin system by calling each plugin's `apply` method, allowing plugins to register their event listeners.
35 |
36 | ### Build Phase
37 |
38 | The build phase begins when webpack encounters your entry points. For each entry, webpack starts building a dependency graph by resolving modules and their dependencies.
39 |
40 | ```mermaid
41 | graph LR
42 | A[entry.js] --> B[utils.js]
43 | A --> C[components/Header.js]
44 | C --> D[Header.css]
45 | C --> E[logo.png]
46 | B --> F[lodash]
47 | A --> G[config.json]
48 |
49 | style A fill:#e1f5fe
50 | style F fill:#f3e5f5
51 | style D fill:#e8f5e8
52 | style E fill:#fff3e0
53 | ```
54 |
55 | webpack uses [enhanced-resolve](https://github.com/webpack/enhanced-resolve) to handle module resolution, following Node.js resolution rules with extensions for things like aliases and custom extensions.
56 |
57 | ### Seal Phase
58 |
59 | After building the module graph, webpack "seals" the compilation and begins optimization. This is where tree shaking, module concatenation (scope hoisting), and other optimizations happen.
60 |
61 | The [SplitChunksPlugin](https://github.com/webpack/webpack/blob/main/lib/optimize/SplitChunksPlugin.js) also runs during this phase, analyzing the module graph to determine optimal chunk splitting strategies.
62 |
63 | ### Emit Phase
64 |
65 | Finally, webpack generates the actual output files and writes them to the filesystem. This includes creating source maps if configured and running any final asset processing plugins.
66 |
67 | ## Core Components
68 |
69 | ### Compiler
70 |
71 | The [Compiler](https://github.com/webpack/webpack/blob/main/lib/Compiler.js) manages the entire build lifecycle. It provides hooks like `beforeRun`, `run`, `compilation`, `emit`, and `done` that plugins use to extend webpack's functionality.
72 |
73 | Think of the Compiler as webpack's event emitter - it coordinates the build process and notifies plugins when significant events occur.
74 |
75 | ### Compilation
76 |
77 | A [Compilation](https://github.com/webpack/webpack/blob/main/lib/Compilation.js) represents a single build with a specific set of resources. While the Compiler manages multiple compilations (like in watch mode), each Compilation handles the processing of modules for one build.
78 |
79 | The Compilation object contains:
80 | - All modules being processed
81 | - The dependency graph
82 | - Generated chunks
83 | - Assets to be emitted
84 |
85 | ### Module Graph
86 |
87 | The [ModuleGraph](https://github.com/webpack/webpack/blob/main/lib/ModuleGraph.js) tracks dependencies between modules and enables sophisticated optimizations. It's separate from the modules themselves, allowing webpack to analyze relationships without duplicating module data.
88 |
89 | ```mermaid
90 | graph TD
91 | A[ModuleGraph] --> B[Module Dependencies]
92 | A --> C[Dependency Connections]
93 | A --> D[Module Exports/Imports]
94 |
95 | B --> E[Static Dependencies]
96 | B --> F[Dynamic Dependencies]
97 |
98 | C --> G[Strong Dependencies]
99 | C --> H[Weak Dependencies]
100 |
101 | D --> I[Used Exports]
102 | D --> J[Unused Exports - Tree Shake]
103 | ```
104 |
105 | This separation allows webpack to perform advanced optimizations like tree shaking without modifying the original module representations.
106 |
107 | ## Module Resolution Deep Dive
108 |
109 | webpack's module resolution is handled by [enhanced-resolve](https://github.com/webpack/enhanced-resolve), which extends Node.js resolution with webpack-specific features.
110 |
111 | The resolution process follows these steps:
112 |
113 | 1. **Parse the request** - Extract module name, path, and query parameters
114 | 2. **Apply aliases** - Check if the request matches any configured aliases
115 | 3. **Try extensions** - Append extensions like `.js`, `.json`, `.ts` until a file is found
116 | 4. **Check main fields** - Look for `main`, `module`, `browser` fields in package.json
117 | 5. **Resolve** - Return the final resolved path
118 |
119 | webpack caches resolution results for performance, which is why changes to `node_modules` sometimes require clearing webpack's cache.
120 |
121 | ## Loaders and Transformations
122 |
123 | Loaders transform files before they're processed by webpack. They run in reverse order (right to left) and can be chained together:
124 |
125 | ```mermaid
126 | graph LR
127 | A[style.scss] --> B[sass-loader]
128 | B --> C[css-loader]
129 | C --> D[style-loader]
130 | D --> E[JS Module]
131 |
132 | B -.-> F[Compiles Sass to CSS]
133 | C -.-> G[Processes CSS imports/urls]
134 | D -.-> H[Injects CSS into DOM]
135 | ```
136 |
137 | Each loader receives the output of the previous loader and must return JavaScript code or pass the result to the next loader.
138 |
139 | Popular loaders include [babel-loader](https://github.com/babel/babel-loader) for JavaScript transformation, [css-loader](https://github.com/webpack/css-loader) for CSS processing, and webpack's asset modules for asset handling.
140 |
141 | ## Plugin System Architecture
142 |
143 | webpack's plugin system is built on [Tapable](https://github.com/webpack/tapable), which provides various hook types following the [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern).
144 |
145 | ```mermaid
146 | graph TD
147 | A[webpack Compiler] --> B[Tapable Hooks]
148 | B --> C[SyncHook]
149 | B --> D[AsyncSeriesHook]
150 | B --> E[AsyncParallelHook]
151 | B --> F[SyncWaterfallHook]
152 |
153 | C --> G[Plugins tap synchronously]
154 | D --> H[Plugins tap with promises/callbacks]
155 | E --> I[Plugins run in parallel]
156 | F --> J[Plugins modify data in sequence]
157 |
158 | G --> K[Execution: plugin1 → plugin2 → plugin3]
159 | H --> L[Execution: await plugin1 → await plugin2]
160 | I --> M["Execution: Promise.all([plugin1, plugin2])"]
161 | J --> N[Execution: data → plugin1 → plugin2 → result]
162 | ```
163 |
164 | This system allows plugins to run at precisely the right moments in webpack's lifecycle, from initial configuration parsing to final asset emission.
165 |
166 | ## Optimization Strategies
167 |
168 | webpack applies numerous optimizations to reduce bundle size and improve runtime performance:
169 |
170 | ### Tree Shaking
171 |
172 | Tree shaking eliminates unused code by analyzing ES6 import/export statements. webpack marks unused exports during compilation and removes them during minification.
173 |
174 | The process relies on static analysis, so it works best with ES6 modules rather than CommonJS. Libraries like [Lodash](https://lodash.com/) provide ES6 versions specifically to enable better tree shaking.
175 |
176 | ### Code Splitting
177 |
178 | webpack automatically splits code into chunks based on several strategies:
179 |
180 | **Entry point splitting** - Each entry point becomes a separate chunk
181 | **Dynamic imports** - `import()` statements create separate chunks
182 | **SplitChunks optimization** - Shared dependencies are extracted into vendor chunks
183 |
184 | ```mermaid
185 | graph TD
186 | A[Original Bundle] --> B[Main Chunk]
187 | A --> C[Vendor Chunk]
188 | A --> D[Dynamic Chunk 1]
189 | A --> E[Dynamic Chunk 2]
190 |
191 | B --> F[App-specific code]
192 | C --> G[node_modules dependencies]
193 | D --> H[Lazy-loaded feature A]
194 | E --> I[Lazy-loaded feature B]
195 | ```
196 |
197 | ### Module Concatenation
198 |
199 | Also known as "scope hoisting," this optimization combines modules into fewer scopes to reduce function call overhead and enable better minification.
200 |
201 | The [ModuleConcatenationPlugin](https://github.com/webpack/webpack/blob/main/lib/optimize/ModuleConcatenationPlugin.js) analyzes which modules can be safely concatenated without affecting behavior.
202 |
203 | ## Development vs Production
204 |
205 | webpack behaves differently in development and production modes to optimize for different priorities:
206 |
207 | **Development mode** prioritizes fast rebuilds and debugging capabilities:
208 | - Minimal optimizations for faster builds
209 | - Source maps for easier debugging
210 | - Hot Module Replacement for live updates
211 | - Detailed error messages and warnings
212 |
213 | **Production mode** focuses on optimal bundle size and runtime performance:
214 | - Full optimization pipeline including minification
215 | - Advanced tree shaking and dead code elimination
216 | - Optimal chunk splitting for caching
217 | - Compressed output and minimal error messages
218 |
219 | ## Memory and Performance Considerations
220 |
221 | webpack can consume significant memory during compilation, especially for large projects. Key factors affecting performance include:
222 |
223 | **Module resolution caching** - webpack caches resolution results, but too many files can consume memory
224 |
225 | **Webpack Dev Server** uses an in-memory filesystem for faster rebuilds during development
226 |
227 | **Parallel processing** - webpack uses worker pools for CPU-intensive tasks like minification
228 |
229 | Study webpack's [build performance guide](https://webpack.js.org/guides/build-performance/) for detailed optimization strategies.
230 |
231 | ## Integration Points
232 |
233 | ### File System Abstraction
234 |
235 | webpack abstracts file system operations through a unified interface, allowing it to work with different filesystem implementations including in-memory filesystems for testing.
236 |
237 | See [webpack's filesystem utilities](https://github.com/webpack/webpack/tree/main/lib/util/fs.js) for implementation details.
238 |
239 | ### Module Formats
240 |
241 | webpack supports multiple module formats and can transform between them:
242 |
243 | - **ES6 Modules** (`import`/`export`) - Preferred for tree shaking
244 | - **CommonJS** (`require`/`module.exports`) - Node.js standard
245 | - **AMD** (`define`/`require`) - Asynchronous Module Definition
246 | - **System.js** - Universal module loader
247 |
248 | The [webpack module parsers](https://github.com/webpack/webpack/tree/main/lib/javascript) handle parsing and transformation between these formats.
249 |
250 | ## Runtime Architecture
251 |
252 | webpack generates a runtime that manages module loading and execution in the browser:
253 |
254 | ```mermaid
255 | graph TD
256 | A[webpack Runtime] --> B[Module Cache]
257 | A --> C[Chunk Loading]
258 | A --> D[Module Resolution]
259 |
260 | B --> E[Prevents duplicate loading]
261 | C --> F["Dynamic import() handling"]
262 | D --> G[Module ID to function mapping]
263 |
264 | F --> H["fetch() for chunks"]
265 | F --> I[JSONP for legacy support]
266 | F --> J["import() for modern browsers"]
267 | ```
268 |
269 | The runtime size depends on features used - basic bundling has minimal runtime overhead, while features like code splitting add more runtime code.
270 |
271 | Examine [webpack's runtime templates](https://github.com/webpack/webpack/tree/main/lib/runtime) to understand how different features affect runtime size.
272 |
273 | ## Debugging webpack
274 |
275 | Understanding webpack's internal state helps debug complex build issues:
276 |
277 | **Enable detailed stats** with `webpack --stats verbose` to see detailed compilation information
278 |
279 | **Use webpack-bundle-analyzer** to visualize bundle composition and identify optimization opportunities
280 |
281 | **Examine webpack's internal state** by adding logging to plugins or using Node.js debugging tools
282 |
283 | The [webpack CLI debugging options](https://webpack.js.org/api/cli/#debug-options) provide various flags for troubleshooting build issues.
284 |
285 | ## Contributing to webpack Core
286 |
287 | When contributing to webpack itself, focus on these key areas:
288 |
289 | **Performance impact** - Profile your changes to ensure they don't slow down builds significantly
290 |
291 | **Backward compatibility** - webpack maintains extensive backward compatibility for existing projects
292 |
293 | **Test coverage** - Add tests that cover both successful scenarios and error conditions
294 |
295 | **Documentation** - Update relevant documentation for user-facing changes
296 |
297 | webpack's architecture has evolved over many years to handle the complexity of modern web applications while maintaining performance and extensibility. Understanding these patterns will help you contribute effectively and build better tools on top of webpack's foundation.
298 |
--------------------------------------------------------------------------------
/docs/technical-guides/testing.md:
--------------------------------------------------------------------------------
1 | # Testing webpack Code
2 |
3 | Testing webpack code is different from testing typical web applications. Instead of testing user interfaces or API endpoints, you're testing build processes, file transformations, and bundle generation.
4 |
5 | This guide shows you practical testing patterns using Node.js built-in test runner, with detailed explanations of what each part does.
6 |
7 | ## Why Test webpack Code?
8 |
9 | When you build webpack plugins or loaders, your code runs during the build process and affects how other people's applications get bundled. Testing ensures:
10 |
11 | - Your plugin works with different webpack configurations
12 | - File transformations produce expected results
13 | - Build processes complete successfully
14 | - Error handling works correctly
15 |
16 | ## Basic Test Setup
17 |
18 | Node.js 18+ includes a built-in test runner, so no extra dependencies needed! Here's the simplest possible test setup:
19 |
20 | ```javascript
21 | // test/basic-test.js
22 |
23 | // Import Node.js built-in testing tools
24 | import { test, describe } from 'node:test';
25 | import assert from 'node:assert';
26 |
27 | // Import webpack itself
28 | import webpack from 'webpack';
29 |
30 | // Import Node.js path utilities
31 | import { fileURLToPath } from 'node:url';
32 | import path from 'node:path';
33 |
34 | // Get current directory (needed in ES modules)
35 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
36 |
37 | // Group related tests together
38 | describe('My First webpack Test', () => {
39 |
40 | // Define a single test case
41 | test('webpack compiles without errors', async () => {
42 |
43 | // Step 1: Create a simple webpack configuration
44 | const config = {
45 | mode: 'development', // Don't minify, easier to debug
46 | entry: './fixtures/simple.js', // File to build from
47 | output: {
48 | path: path.join(__dirname, 'temp'), // Where to put result
49 | filename: 'bundle.js' // What to name result
50 | }
51 | };
52 |
53 | // Step 2: Run webpack with our configuration
54 | const stats = await runWebpack(config);
55 |
56 | // Step 3: Check that compilation succeeded
57 | assert.ok(!stats.hasErrors(), 'webpack should compile without errors');
58 |
59 | // Step 4: Verify that the output file was created
60 | const assets = stats.compilation.assets;
61 | assert.ok(assets['bundle.js'], 'Should create bundle.js file');
62 | });
63 | });
64 |
65 | // Helper function to run webpack and return a Promise
66 | // This makes testing much easier since webpack's API uses callbacks
67 | function runWebpack(config) {
68 | return new Promise((resolve, reject) => {
69 | // webpack() takes a config and a callback function
70 | webpack(config, (err, stats) => {
71 | if (err) {
72 | // Build tool error (like invalid config)
73 | reject(err);
74 | } else {
75 | // Normal completion (might still have compilation errors)
76 | resolve(stats);
77 | }
78 | });
79 | });
80 | }
81 | ```
82 |
83 | You'll also need a simple test fixture:
84 |
85 | ```javascript
86 | // test/fixtures/simple.js
87 |
88 | // This is the simplest possible entry file for testing
89 | console.log('Hello from webpack test!');
90 |
91 | // Export something so webpack has content to bundle
92 | export default 'test-content';
93 | ```
94 |
95 | ## Testing Plugin Basics
96 |
97 | Here's how to test a simple webpack plugin step by step:
98 |
99 | ```javascript
100 | // test/plugin-test.js
101 |
102 | import { test, describe } from 'node:test';
103 | import assert from 'node:assert';
104 | import webpack from 'webpack';
105 |
106 | // Let's test this simple plugin that adds a text file to the build
107 | class HelloPlugin {
108 | apply(compiler) {
109 | // Hook into webpack's compilation process
110 | compiler.hooks.emit.tap('HelloPlugin', (compilation) => {
111 | // Add a new file to the build output
112 | compilation.assets['hello.txt'] = {
113 | source: () => 'Hello from plugin!',
114 | size: () => 18
115 | };
116 | });
117 | }
118 | }
119 |
120 | describe('HelloPlugin Tests', () => {
121 |
122 | test('plugin adds hello.txt to build output', async () => {
123 |
124 | // Step 1: Create webpack config that uses our plugin
125 | const config = {
126 | mode: 'development',
127 | entry: './fixtures/simple.js',
128 | plugins: [
129 | new HelloPlugin() // Add our plugin to the build
130 | ]
131 | };
132 |
133 | // Step 2: Run webpack
134 | const stats = await runWebpack(config);
135 |
136 | // Step 3: Make sure no errors occurred
137 | assert.ok(!stats.hasErrors(), 'Plugin should not cause errors');
138 |
139 | // Step 4: Check that our plugin added the expected file
140 | const assets = stats.compilation.assets;
141 | assert.ok(assets['hello.txt'], 'Plugin should add hello.txt file');
142 |
143 | // Step 5: Verify the file content is correct
144 | const content = assets['hello.txt'].source();
145 | assert.strictEqual(content, 'Hello from plugin!', 'File content should match');
146 | });
147 |
148 | test('plugin works with different webpack modes', async () => {
149 |
150 | // Test that our plugin works in production mode too
151 | const config = {
152 | mode: 'production', // This enables minification and optimizations
153 | entry: './fixtures/simple.js',
154 | plugins: [new HelloPlugin()]
155 | };
156 |
157 | const stats = await runWebpack(config);
158 |
159 | // Even with optimizations, our plugin should still work
160 | assert.ok(!stats.hasErrors(), 'Plugin should work in production mode');
161 | assert.ok(stats.compilation.assets['hello.txt'], 'Should still create file in production');
162 | });
163 | });
164 |
165 | // Same helper function as before
166 | function runWebpack(config) {
167 | return new Promise((resolve, reject) => {
168 | webpack(config, (err, stats) => {
169 | if (err) reject(err);
170 | else resolve(stats);
171 | });
172 | });
173 | }
174 | ```
175 |
176 | ## Testing Loaders Simply
177 |
178 | Loaders transform files. Here's how to test a basic loader that converts text to uppercase:
179 |
180 | ```javascript
181 | // test/loader-test.js
182 |
183 | import { test, describe } from 'node:test';
184 | import assert from 'node:assert';
185 | import webpack from 'webpack';
186 | import path from 'node:path';
187 |
188 | // Simple loader that converts content to uppercase
189 | function uppercaseLoader(source) {
190 | // 'source' is the file content as a string
191 | // Return the transformed content
192 | return source.toUpperCase();
193 | }
194 |
195 | describe('Uppercase Loader Tests', () => {
196 |
197 | test('loader converts text to uppercase', async () => {
198 |
199 | // Step 1: Create a test file with lowercase text
200 | // (You'd create test/fixtures/lowercase.txt with content: "hello world")
201 |
202 | // Step 2: Configure webpack to use our loader
203 | const config = {
204 | mode: 'development',
205 | entry: './fixtures/lowercase.txt', // Process this file
206 | module: {
207 | rules: [{
208 | test: /\.txt$/, // Apply to .txt files
209 | use: [{
210 | loader: path.resolve(__dirname, '../uppercase-loader.js') // Our loader
211 | }]
212 | }]
213 | }
214 | };
215 |
216 | // Step 3: Run webpack
217 | const stats = await runWebpack(config);
218 |
219 | // Step 4: Check for errors
220 | assert.ok(!stats.hasErrors(), 'Loader should not cause errors');
221 |
222 | // Step 5: Find the processed module
223 | const modules = Array.from(stats.compilation.modules);
224 | const txtModule = modules.find(m => m.resource && m.resource.endsWith('.txt'));
225 |
226 | assert.ok(txtModule, 'Should find the processed .txt module');
227 |
228 | // The exact way to check transformed content depends on your loader
229 | // This is a simplified example
230 | });
231 | });
232 |
233 | function runWebpack(config) {
234 | return new Promise((resolve, reject) => {
235 | webpack(config, (err, stats) => {
236 | if (err) reject(err);
237 | else resolve(stats);
238 | });
239 | });
240 | }
241 | ```
242 |
243 | ## Testing Error Handling
244 |
245 | Good plugins handle errors gracefully. Here's how to test error conditions:
246 |
247 | ```javascript
248 | // test/error-handling-test.js
249 |
250 | import { test, describe } from 'node:test';
251 | import assert from 'node:assert';
252 | import webpack from 'webpack';
253 |
254 | // Plugin that can be configured to throw errors (for testing)
255 | class TestErrorPlugin {
256 | constructor(options = {}) {
257 | this.shouldError = options.shouldError || false;
258 | }
259 |
260 | apply(compiler) {
261 | compiler.hooks.emit.tap('TestErrorPlugin', (compilation) => {
262 | if (this.shouldError) {
263 | // Add an error to the compilation
264 | compilation.errors.push(new Error('Plugin intentionally failed'));
265 | }
266 | });
267 | }
268 | }
269 |
270 | describe('Error Handling Tests', () => {
271 |
272 | test('webpack reports plugin errors correctly', async () => {
273 |
274 | // Step 1: Configure plugin to cause an error
275 | const config = {
276 | mode: 'development',
277 | entry: './fixtures/simple.js',
278 | plugins: [
279 | new TestErrorPlugin({ shouldError: true }) // Make it error
280 | ]
281 | };
282 |
283 | // Step 2: Run webpack (it will have errors)
284 | const stats = await runWebpack(config);
285 |
286 | // Step 3: Verify that errors were properly reported
287 | assert.ok(stats.hasErrors(), 'Should report errors when plugin fails');
288 |
289 | // Step 4: Check error details
290 | const errors = stats.compilation.errors;
291 | assert.ok(errors.length > 0, 'Should have at least one error');
292 | assert.match(errors[0].message, /intentionally failed/, 'Should report our custom error');
293 | });
294 |
295 | test('webpack handles missing entry files', async () => {
296 |
297 | // Step 1: Create config with non-existent entry file
298 | const config = {
299 | mode: 'development',
300 | entry: './does-not-exist.js' // This file doesn't exist
301 | };
302 |
303 | // Step 2: Run webpack
304 | const stats = await runWebpack(config);
305 |
306 | // Step 3: Should have errors about missing file
307 | assert.ok(stats.hasErrors(), 'Should report error for missing entry file');
308 |
309 | const errors = stats.compilation.errors;
310 | const errorMessage = errors[0].message;
311 | assert.match(errorMessage, /Module not found/, 'Should report module not found error');
312 | });
313 | });
314 |
315 | function runWebpack(config) {
316 | return new Promise((resolve, reject) => {
317 | webpack(config, (err, stats) => {
318 | if (err) reject(err);
319 | else resolve(stats);
320 | });
321 | });
322 | }
323 | ```
324 |
325 | ## Debugging Test Failures
326 |
327 | When tests fail, you need powerful debugging tools. Node.js provides excellent built-in debugging capabilities that connect directly to Chrome DevTools.
328 |
329 | ### Node.js Built-in Debugger (Recommended)
330 |
331 | Node.js includes a built-in debugger that opens Chrome DevTools. This is the most powerful way to debug webpack tests:
332 |
333 | ```bash
334 | # Debug a specific test file
335 | node --inspect-brk --test test/my-test.js
336 |
337 | # Debug all tests (they'll pause at the first test)
338 | node --inspect-brk --test
339 |
340 | # Debug with specific port
341 | node --inspect-brk=9230 --test test/my-test.js
342 | ```
343 |
344 | **Steps to use:**
345 |
346 | 1. Run the command above
347 | 2. Open Chrome and go to `chrome://inspect`
348 | 3. Click "Open dedicated DevTools for Node"
349 | 4. Your test will pause at the first line - set breakpoints and continue
350 |
351 | ### VS Code Debugging
352 |
353 | For VS Code users, create `.vscode/launch.json`:
354 |
355 | ```json
356 | {
357 | "version": "0.2.0",
358 | "configurations": [
359 | {
360 | "name": "Debug webpack Tests",
361 | "type": "node",
362 | "request": "launch",
363 | "program": "${workspaceFolder}/node_modules/.bin/node",
364 | "args": [
365 | "--test",
366 | "${workspaceFolder}/test/my-test.js"
367 | ],
368 | "console": "integratedTerminal",
369 | "internalConsoleOptions": "neverOpen"
370 | },
371 | {
372 | "name": "Debug Current Test File",
373 | "type": "node",
374 | "request": "launch",
375 | "program": "${workspaceFolder}/node_modules/.bin/node",
376 | "args": [
377 | "--test",
378 | "${file}"
379 | ],
380 | "console": "integratedTerminal"
381 | }
382 | ]
383 | }
384 | ```
385 |
386 | ### Adding Debug Information to Tests
387 |
388 | You can also add helpful logging for when debugging isn't enough:
389 |
390 | ```javascript
391 | // test/debugging-test.js
392 |
393 | import { test } from 'node:test';
394 | import assert from 'node:assert';
395 | import webpack from 'webpack';
396 |
397 | test('debug failing compilation', async () => {
398 | const config = {
399 | mode: 'development',
400 | entry: './fixtures/simple.js'
401 | };
402 |
403 | const stats = await runWebpack(config);
404 |
405 | // Add a debugger statement to pause execution
406 | debugger; // Execution will pause here when using --inspect-brk
407 |
408 | // Log compilation details when needed
409 | if (stats.hasErrors() || process.env.DEBUG) {
410 | logCompilationDetails(stats);
411 | }
412 |
413 | assert.ok(!stats.hasErrors(), 'Should compile without errors');
414 | });
415 |
416 | function logCompilationDetails(stats) {
417 | console.log('\n=== COMPILATION DEBUG INFO ===');
418 |
419 | if (stats.hasErrors()) {
420 | console.log('ERRORS:');
421 | stats.compilation.errors.forEach((error, index) => {
422 | console.log(` ${index + 1}. ${error.message}`);
423 | if (error.stack) console.log(` Stack: ${error.stack}`);
424 | });
425 | }
426 |
427 | if (stats.hasWarnings()) {
428 | console.log('WARNINGS:');
429 | stats.compilation.warnings.forEach((warning, index) => {
430 | console.log(` ${index + 1}. ${warning.message}`);
431 | });
432 | }
433 |
434 | console.log(`Build time: ${stats.endTime - stats.startTime}ms`);
435 | console.log(`Modules: ${stats.compilation.modules.size}`);
436 | console.log(`Assets: ${Object.keys(stats.compilation.assets).length}`);
437 |
438 | // Log asset details
439 | Object.entries(stats.compilation.assets).forEach(([name, asset]) => {
440 | console.log(` ${name}: ${asset.size()} bytes`);
441 | });
442 | }
443 |
444 | function runWebpack(config) {
445 | return new Promise((resolve, reject) => {
446 | webpack(config, (err, stats) => {
447 | if (err) reject(err);
448 | else resolve(stats);
449 | });
450 | });
451 | }
452 | ```
453 |
454 | ### Additional Debugging Tools
455 |
456 | **Node.js Inspector API**: For programmatic debugging, you can use Node's inspector module:
457 |
458 | ```javascript
459 | import inspector from 'node:inspector';
460 |
461 | // Enable debugging programmatically
462 | if (!inspector.url()) {
463 | inspector.open(9229, 'localhost', true);
464 | }
465 |
466 | // Add breakpoint in code
467 | inspector.Session.prototype.post('Debugger.setBreakpointByUrl', {
468 | lineNumber: 10,
469 | url: 'file:///path/to/test.js'
470 | });
471 | ```
472 |
473 | **Environment Variables**: Use debug flags to get more information:
474 |
475 | ```bash
476 | # Enable more verbose webpack output
477 | DEBUG=webpack* node --test test/my-test.js
478 |
479 | # Node.js debug output
480 | NODE_DEBUG=* node --test test/my-test.js
481 |
482 | # Custom debug logging in your tests
483 | DEBUG=1 node --test test/my-test.js
484 | ```
485 |
486 | ### Debugging Webpack-Specific Issues
487 |
488 | For webpack compilation debugging, you can enable webpack's built-in debug features:
489 |
490 | ```javascript
491 | const config = {
492 | mode: 'development',
493 | entry: './fixtures/simple.js',
494 | stats: 'verbose', // More detailed output
495 | infrastructureLogging: {
496 | level: 'verbose', // Enable webpack's internal logging
497 | debug: /webpack/
498 | }
499 | };
500 | ```
501 |
502 | These debugging tools are much more powerful than simple console logging and will help you understand exactly what's happening in your webpack tests. The Chrome DevTools integration provides the same debugging experience you're used to in the browser, but for Node.js code.
503 |
504 | ## Running Your Tests
505 |
506 | To run these tests, use Node.js built-in test runner:
507 |
508 | ```bash
509 | # Run all test files
510 | node --test
511 |
512 | # Run specific test file
513 | node --test test/basic-test.js
514 |
515 | # Run with more detailed output
516 | node --test --verbose
517 |
518 | # Run tests that match a pattern
519 | node --test --test-name-pattern="plugin"
520 | ```
521 |
522 | ## Learning from webpack's Tests
523 |
524 | webpack itself has extensive tests you can learn from. Look at these directories in the [webpack repository](https://github.com/webpack/webpack):
525 |
526 | - `test/configCases/` - Tests different webpack configurations
527 | - `test/statsCases/` - Tests webpack's output statistics
528 | - `test/hotCases/` - Tests Hot Module Replacement
529 | - `test/helpers/` - Utility functions for testing
530 |
531 | Study these examples to see how the webpack team tests complex scenarios.
532 |
533 | ## Key Testing Principles
534 |
535 | **Test real compilation processes** rather than mocking webpack internals. This catches integration issues that unit tests might miss.
536 |
537 | **Use simple, focused test cases** that verify one thing at a time. Large complex tests are hard to debug when they fail.
538 |
539 | **Always test error conditions** as well as success cases. Users depend on clear error messages when things go wrong.
540 |
541 | **Add debugging output** when tests fail so you can understand what went wrong.
542 |
543 | **Keep test fixtures simple** - use minimal entry files and configurations that focus on what you're testing.
544 |
545 | The goal is creating tests that give you confidence your webpack plugins and loaders work correctly while being easy to understand and maintain.
546 |
--------------------------------------------------------------------------------