├── 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 |
4 | 5 | webpack 6 | 7 |
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 | --------------------------------------------------------------------------------