├── .gitignore ├── LICENSE ├── README.md ├── part1 ├── README.md ├── css-extract │ ├── README.md │ ├── package.json │ ├── src │ │ ├── changeColor.js │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ ├── webpack.config.dev.js │ └── webpack.config.prod.js ├── example1 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── APIStuff.js │ │ ├── UIStuff.js │ │ ├── extraFile.js │ │ ├── index.js │ │ └── styles.css │ └── webpack.config.js ├── example2 │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.js │ └── webpack.config.js ├── example3 │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.js │ └── webpack.config.js ├── example4 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ └── webpack.config.js ├── example5 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ └── webpack.config.js ├── example6 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ ├── webpack.config.dev.js │ └── webpack.config.prod.js ├── example7 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ ├── webpack.config.dev.js │ └── webpack.config.prod.js └── html-reload │ ├── README.md │ ├── package.json │ ├── src │ ├── index.html │ ├── index.js │ └── styles.css │ ├── webpack.config.dev.js │ └── webpack.config.prod.js ├── part2 ├── README.md └── example1 │ ├── .babelrc │ ├── .eslintrc │ ├── package.json │ ├── src │ ├── index.html │ ├── index.js │ └── styles.css │ ├── webpack.config.dev.js │ └── webpack.config.prod.js └── zh-TW ├── README.md ├── part1 ├── README.md ├── css-extract │ ├── README.md │ ├── package.json │ ├── src │ │ ├── changeColor.js │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ ├── webpack.config.dev.js │ └── webpack.config.prod.js ├── example1 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── APIStuff.js │ │ ├── UIStuff.js │ │ ├── extraFile.js │ │ ├── index.js │ │ └── styles.css │ └── webpack.config.js ├── example2 │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.js │ └── webpack.config.js ├── example3 │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.js │ └── webpack.config.js ├── example4 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ └── webpack.config.js ├── example5 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ └── webpack.config.js ├── example6 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ ├── webpack.config.dev.js │ └── webpack.config.prod.js ├── example7 │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── index.js │ │ └── styles.css │ ├── webpack.config.dev.js │ └── webpack.config.prod.js └── html-reload │ ├── README.md │ ├── package.json │ ├── src │ ├── index.html │ ├── index.js │ └── styles.css │ ├── webpack.config.dev.js │ └── webpack.config.prod.js └── part2 ├── README.md └── example1 ├── .babelrc ├── .eslintrc ├── package.json ├── src ├── index.html ├── index.js └── styles.css ├── webpack.config.dev.js └── webpack.config.prod.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | bundle.js 4 | npm-debug.log* 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Aria Fallah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Beginner Webpack Tutorial :school: 2 | 3 | Starting off with webpack was hard for me. I want to create a beginner friendly and comprehensive 4 | intro to webpack. 5 | 6 | - [Part 1](https://github.com/AriaFallah/WebpackTutorial/tree/master/part1) - Webpack Basics and configuration. 7 | - [Part 2](https://github.com/AriaFallah/WebpackTutorial/tree/master/part2) - Babel, linting, and environment variables. 8 | 9 | ### Translations 10 | - [Chinese Traditional](https://github.com/AriaFallah/WebpackTutorial/tree/master/zh-TW) 11 | 12 | ### Gitbook 13 | 14 | - [Webpack Tutoiral Gitbook 繁體中文](https://github.com/neighborhood999/webpack-tutorial-gitbook) 15 | -------------------------------------------------------------------------------- /part1/README.md: -------------------------------------------------------------------------------- 1 | # Beginner Webpack Tutorial Part 1 - Introduction To Webpack :zap: 2 | 3 | This is for the people like me whose first intro to webpack was a repository similar to: 4 | 5 | * https://github.com/davezuko/react-redux-starter-kit 6 | * https://github.com/webpack/react-starter 7 | 8 | While these repositories are very well put together, they aren't necessarily the best learning tools. 9 | In my case, I got pretty confused trying to understand what was going on, and scrapped together my 10 | understanding from a lot of scattered resources. 11 | 12 | I hope that this tutorial can make Webpack easy to learn. 13 | 14 | ## Requirements 15 | 16 | At the very least you are expected to know the basics of node.js and npm. 17 | 18 | ## Contributing 19 | 20 | I will gladly accept any and all contributions/corrections. If you have any questions, 21 | feel free to leave them as issues. If I made mistakes, please point them out. Finally, if you feel 22 | that I left anything out, or could have explained something better make sure to leave an issue or 23 | make a pull request. 24 | 25 | ## Table of Contents 26 | 27 | * [Why Webpack?](#why-webpack) 28 | * [The Basics](#the-basics) 29 | * [Installation](#installation) 30 | * [Bundling](#bundling) 31 | * [Loaders](#loaders) 32 | * [Plugins](#plugins) 33 | * [Your Config File](#your-config-file) 34 | * [A Minimal Example](#a-minimal-example) 35 | * [Introducing Plugins](#introducing-plugins) 36 | * [A More Complete Example](#a-more-complete-example) 37 | * [Introducing Loaders](#introducing-loaders) 38 | * [Adding More Plugins](#adding-more-plugins) 39 | * [The Development Server](#the-development-server) 40 | * [Start Coding](#start-coding) 41 | * [Conclusion](#conclusion) 42 | * [Closing Thoughts](#closing-thoughts) 43 | 44 | ## Why Webpack? 45 | 46 | Because every single react/redux tutorial assumes you know it :cry: 47 | 48 | More realistically here are some reasons you would want to use webpack. 49 | 50 | Lets you: 51 | * Bundle your js files into a single file 52 | * Use npm packages in your frontend code 53 | * Write ES6/ES7 JavaScript (with help from babel) 54 | * Minify/Optimize code 55 | * Turn LESS/SCSS into CSS 56 | * Use HMR (Hot Module Replacement) 57 | * Include any type of file into your JavaScript 58 | * A lot more advanced stuff, which I won't cover 59 | 60 | ##### Why do I want these features? 61 | 62 | * Bundle JS files - Lets you write modular JavaScript, but you do not need to include a separate 63 | ` 65 | 66 | ``` 67 | -------------------------------------------------------------------------------- /part1/css-extract/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-extract", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "webpack.config.js", 6 | "scripts": { 7 | "build": "webpack --config webpack.config.prod.js", 8 | "dev": "webpack-dev-server --config webpack.config.dev.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "css-loader": "^0.23.1", 15 | "extract-text-webpack-plugin": "^1.0.1", 16 | "html-webpack-plugin": "^2.8.1", 17 | "style-loader": "^0.13.0", 18 | "webpack": "^1.12.13", 19 | "webpack-dev-server": "^1.14.1" 20 | }, 21 | "dependencies": { 22 | "pleasejs": "^0.4.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /part1/css-extract/src/changeColor.js: -------------------------------------------------------------------------------- 1 | var Please = require('pleasejs') 2 | var div = document.getElementById('color') 3 | var button = document.getElementById('button') 4 | 5 | function changeColor() { 6 | div.style.backgroundColor = Please.make_color() 7 | console.log('pls do work') 8 | } 9 | 10 | button.addEventListener('click', changeColor) 11 | -------------------------------------------------------------------------------- /part1/css-extract/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Webpack Tutorial 4 | 5 | 6 |

Very Website

7 |
8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /part1/css-extract/src/index.js: -------------------------------------------------------------------------------- 1 | require('./styles.css') 2 | require('./changeColor.js') 3 | -------------------------------------------------------------------------------- /part1/css-extract/src/styles.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: rgb(114, 191, 190); 3 | text-align: center; 4 | } 5 | 6 | #color { 7 | width: 300px; 8 | height: 300px; 9 | margin: 0 auto; 10 | } 11 | 12 | button { 13 | cursor: pointer; 14 | display: block; 15 | width: 100px; 16 | outline: 0; 17 | border: 0; 18 | margin: 20px auto; 19 | } 20 | -------------------------------------------------------------------------------- /part1/css-extract/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | var HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | module.exports = { 6 | devtool: 'cheap-eval-source-map', 7 | entry: [ 8 | 'webpack-dev-server/client?http://localhost:8080', 9 | 'webpack/hot/dev-server', 10 | './src/index' 11 | ], 12 | output: { 13 | path: path.join(__dirname, 'dist'), 14 | filename: 'bundle.js' 15 | }, 16 | plugins: [ 17 | new webpack.HotModuleReplacementPlugin(), 18 | new HtmlWebpackPlugin({ 19 | template: './src/index.html' 20 | }) 21 | ], 22 | module: { 23 | loaders: [{ 24 | test: /\.css$/, 25 | loaders: ['style', 'css'] 26 | }] 27 | }, 28 | devServer: { 29 | contentBase: './dist', 30 | hot: true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /part1/css-extract/webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | var HtmlWebpackPlugin = require('html-webpack-plugin') 4 | var ExtractTextPlugin = require("extract-text-webpack-plugin"); 5 | 6 | module.exports = { 7 | devtool: 'source-map', 8 | entry: ['./src/index'], 9 | output: { 10 | path: path.join(__dirname, 'dist'), 11 | filename: 'bundle.js' 12 | }, 13 | plugins: [ 14 | new webpack.optimize.UglifyJsPlugin({ 15 | compressor: { 16 | warnings: false, 17 | }, 18 | }), 19 | new webpack.optimize.OccurrenceOrderPlugin(), 20 | new HtmlWebpackPlugin({ 21 | template: './src/index.html' 22 | }), 23 | new ExtractTextPlugin("styles.css") 24 | ], 25 | module: { 26 | loaders: [{ 27 | test: /\.css$/, 28 | loader: ExtractTextPlugin.extract("style-loader", "css-loader") 29 | }] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /part1/example1/README.md: -------------------------------------------------------------------------------- 1 | # Example 1 - Bundling and Loaders 2 | 3 | ![Official Dependency Tree](http://i.imgur.com/YU4xBPQ.png) 4 | 5 | Webpack is formally referred to as a module bundler. If you want an in-depth and accessible explanation 6 | on modules and module bundling definitely check out these two great articles: 7 | [here](https://medium.freecodecamp.com/javascript-modules-a-beginner-s-guide-783f7d7a5fcc#.jw1txw6uh) 8 | and [here](https://medium.com/@preethikasireddy/javascript-modules-part-2-module-bundling-5020383cf306#.lfnspler2). 9 | We're gonna keep it simple. The way that it works is that you specify a single file as your entry point. 10 | This file will be the root of your tree. Then every time you `require` a file from another file it's 11 | added to the tree. When you run `webpack`, all these files/modules are bundled into a single file. 12 | 13 | Here's a simple example: 14 | 15 | ![Dependency Tree](http://i.imgur.com/dSghwwL.png) 16 | 17 | Given this picture you could have the directory: 18 | 19 | ``` 20 | MyDirectory 21 | |- index.js 22 | |- UIStuff.js 23 | |- APIStuff.js 24 | |- styles.css 25 | |- extraFile.js 26 | ``` 27 | 28 | and this could be the content of your files 29 | 30 | ```javascript 31 | // index.js 32 | require('./styles.css') 33 | require('./UIStuff.js') 34 | require('./APIStuff.js') 35 | 36 | // UIStuff.js 37 | var React = require('React') 38 | React.createClass({ 39 | // stuff 40 | }) 41 | 42 | // APIStuff.js 43 | var fetch = require('fetch') // fetch polyfill 44 | fetch('https://google.com') 45 | ``` 46 | 47 | ```css 48 | /* styles.css */ 49 | body { 50 | background-color: rgb(200, 56, 97); 51 | } 52 | ``` 53 | 54 | When you run `webpack`, you'll get a bundle with the contents of this tree, but `extraFile.js`, which was in the same directory, will not be part of 55 | the bundle because it is not a part of the dependency tree: 56 | 57 | `bundle.js` will look like: 58 | 59 | ```javascript 60 | // contents of styles.css 61 | // contents of UIStuff.js + React 62 | // contents of APIStuff.js + fetch 63 | ``` 64 | 65 | The things that are bundled are only the things that you explicitly required across your files. 66 | 67 | ### Loaders 68 | 69 | As you probably noticed, I did something strange in the above example. I `required` a css file in a javascript file. 70 | 71 | The really cool and interesting thing about webpack is that you can `require` more than just 72 | javascript files. 73 | 74 | There is this thing in webpack called a loader. Using these loaders, you can 75 | `require` anything from `.css` and `.png` to `.html` files. 76 | 77 | For example in the diagram above I had 78 | 79 | ```javascript 80 | // index.js 81 | require('./styles.css') 82 | ``` 83 | 84 | If I include [the style-loader](https://github.com/webpack/style-loader) and the [the css-loader](https://github.com/webpack/css-loader) in my webpack config, this is not only perfectly 85 | valid, but also will actually apply the CSS to my page. 86 | 87 | This is just a single example of the many loaders you can use with webpack. 88 | -------------------------------------------------------------------------------- /part1/example1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example1", 3 | "version": "1.0.0", 4 | "description": "![Official Dependency Tree](http://i.imgur.com/YU4xBPQ.png)", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "fetch": "^1.0.0", 14 | "react": "^0.14.7" 15 | }, 16 | "devDependencies": { 17 | "css-loader": "^0.23.1", 18 | "style-loader": "^0.13.0", 19 | "webpack": "^1.12.14" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /part1/example1/src/APIStuff.js: -------------------------------------------------------------------------------- 1 | var fetch = require('fetch') // fetch polyfill 2 | fetch('https://google.com') 3 | -------------------------------------------------------------------------------- /part1/example1/src/UIStuff.js: -------------------------------------------------------------------------------- 1 | var React = require('React') 2 | React.createClass({ 3 | // stuff 4 | }) 5 | -------------------------------------------------------------------------------- /part1/example1/src/extraFile.js: -------------------------------------------------------------------------------- 1 | console.log('No one likes me') 2 | -------------------------------------------------------------------------------- /part1/example1/src/index.js: -------------------------------------------------------------------------------- 1 | require('./styles.css') 2 | require('./UIStuff.js') 3 | require('./APIStuff.js') 4 | -------------------------------------------------------------------------------- /part1/example1/src/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: rgb(200, 56, 97); 3 | } 4 | -------------------------------------------------------------------------------- /part1/example1/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: ['./src/index'], // .js after index is optional 6 | output: { 7 | path: path.join(__dirname, 'dist'), 8 | filename: 'bundle.js' 9 | }, 10 | plugins: [ 11 | new webpack.optimize.UglifyJsPlugin({ 12 | compressor: { 13 | warnings: false, 14 | }, 15 | }), 16 | new webpack.optimize.OccurrenceOrderPlugin() 17 | ], 18 | module: { 19 | loaders: [{ 20 | test: /\.css$/, 21 | loaders: ['style', 'css'] 22 | }] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /part1/example2/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 - A minimal example 2 | 3 | Say your directory structure looks like this: 4 | 5 | ``` 6 | MyDirectory 7 | |- dist 8 | |- src 9 | |- index.js 10 | |- webpack.config.js 11 | 12 | ``` 13 | 14 | Then a very minimal webpack config you can make is this 15 | 16 | ```javascript 17 | // webpack.config.js 18 | var path = require('path') 19 | 20 | module.exports = { 21 | entry: ['./src/index'], // .js after index is optional 22 | output: { 23 | path: path.join(__dirname, 'dist'), 24 | filename: 'bundle.js' 25 | } 26 | } 27 | ``` 28 | 29 | Going over the new properties one by one: 30 | 31 | * [entry](https://webpack.github.io/docs/configuration.html#entry) - The entrypoint of your bundle, which we discussed in the [bundling](#bundling) section. It's an array because webpack allows multiple entry points if you want to generate multiple bundles. 32 | 33 | * [output](https://webpack.github.io/docs/configuration.html#output) - Dictates the form of the output by webpack 34 | * [path](https://webpack.github.io/docs/configuration.html#output-path) - where to put the bundle 35 | * [filename](https://webpack.github.io/docs/configuration.html#output-filename) - what to call the bundle 36 | 37 | When you run `webpack`, this will create a file called `bundle.js` in the dist folder. 38 | -------------------------------------------------------------------------------- /part1/example2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example2", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "webpack.config.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "MIT" 12 | } 13 | -------------------------------------------------------------------------------- /part1/example2/src/index.js: -------------------------------------------------------------------------------- 1 | console.log('It works!') 2 | -------------------------------------------------------------------------------- /part1/example2/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | 3 | module.exports = { 4 | entry: ['./src/index'], // .js after index is optional 5 | output: { 6 | path: path.join(__dirname, 'dist'), 7 | filename: 'bundle.js' 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /part1/example3/README.md: -------------------------------------------------------------------------------- 1 | # Example 3 - Introducing Plugins 2 | 3 | Imagine that you've used webpack to bundle all your files together, and now you've realized that all 4 | together it's 900KB. This is a problem that can be ameliorated by minifying your bundle. To do this 5 | you need to use a plugin I mentioned earlier called the 6 | [UglifyJsPlugin](https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin). 7 | 8 | Moreover you will need to have webpack installed locally to actually be able to use the plugin. 9 | 10 | npm install --save-dev webpack 11 | 12 | Now you can require webpack and minify your code. 13 | 14 | ```javascript 15 | // webpack.config.js 16 | var path = require('path') 17 | var webpack = require('webpack') 18 | 19 | module.exports = { 20 | entry: ['./src/index'], 21 | output: { 22 | path: path.join(__dirname, 'dist'), 23 | filename: 'bundle.js' 24 | }, 25 | 26 | plugins: [ 27 | new webpack.optimize.UglifyJsPlugin({ 28 | compressor: { 29 | warnings: false, 30 | }, 31 | }) 32 | ] 33 | } 34 | ``` 35 | Going over the new properties one by one: 36 | 37 | * plugins - An array that holds your plugins. 38 | * [webpack.optimize.UglifyJsPlugin](https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin) - Minify your code, and suppress warning messages. 39 | 40 | This time, when you run `webpack`, now that you have the `UglifyJsPlugin` this could reduce your 41 | imaginary 900KB file to 200KB by through processes such as removing all the whitespace. 42 | 43 | You can also add the [OrderOccurencePlugin](https://webpack.github.io/docs/list-of-plugins.html#occurrenceorderplugin) 44 | 45 | > Assign the module and chunk ids by occurrence count. Ids that are used often get lower (shorter) ids. This make ids predictable, reduces to total file size and is recommended. 46 | 47 | To be honest I'm not sure how the underlying mechanisms work, but in the current [webpack2 beta it's included by default](https://gist.github.com/sokra/27b24881210b56bbaff7) so I include it as well. 48 | 49 | ```javascript 50 | // webpack.config.js 51 | var path = require('path') 52 | var webpack = require('webpack') 53 | 54 | module.exports = { 55 | entry: ['./src/index'], 56 | output: { 57 | path: path.join(__dirname, 'dist'), 58 | filename: 'bundle.js' 59 | }, 60 | plugins: [ 61 | new webpack.optimize.UglifyJsPlugin({ 62 | compressor: { 63 | warnings: false, 64 | }, 65 | }), 66 | new webpack.optimize.OccurenceOrderPlugin() 67 | ] 68 | } 69 | ``` 70 | 71 | So now we have written a config that allows us to minify and bundle our javascript. This bundle 72 | could be copied and pasted into another project's directory, and thrown into a ` 60 | 61 | ``` 62 | -------------------------------------------------------------------------------- /zh-TW/part1/css-extract/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-extract", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "webpack.config.js", 6 | "scripts": { 7 | "build": "webpack --config webpack.config.prod.js", 8 | "dev": "webpack-dev-server --config webpack.config.dev.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "css-loader": "^0.23.1", 15 | "extract-text-webpack-plugin": "^1.0.1", 16 | "html-webpack-plugin": "^2.8.1", 17 | "style-loader": "^0.13.0", 18 | "webpack": "^1.12.13", 19 | "webpack-dev-server": "^1.14.1" 20 | }, 21 | "dependencies": { 22 | "pleasejs": "^0.4.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /zh-TW/part1/css-extract/src/changeColor.js: -------------------------------------------------------------------------------- 1 | var Please = require('pleasejs') 2 | var div = document.getElementById('color') 3 | var button = document.getElementById('button') 4 | 5 | function changeColor() { 6 | div.style.backgroundColor = Please.make_color() 7 | console.log('pls do work') 8 | } 9 | 10 | button.addEventListener('click', changeColor) 11 | -------------------------------------------------------------------------------- /zh-TW/part1/css-extract/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Webpack Tutorial 4 | 5 | 6 |

Very Website

7 |
8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /zh-TW/part1/css-extract/src/index.js: -------------------------------------------------------------------------------- 1 | require('./styles.css') 2 | require('./changeColor.js') 3 | -------------------------------------------------------------------------------- /zh-TW/part1/css-extract/src/styles.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: rgb(114, 191, 190); 3 | text-align: center; 4 | } 5 | 6 | #color { 7 | width: 300px; 8 | height: 300px; 9 | margin: 0 auto; 10 | } 11 | 12 | button { 13 | cursor: pointer; 14 | display: block; 15 | width: 100px; 16 | outline: 0; 17 | border: 0; 18 | margin: 20px auto; 19 | } 20 | -------------------------------------------------------------------------------- /zh-TW/part1/css-extract/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | var HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | module.exports = { 6 | devtool: 'cheap-eval-source-map', 7 | entry: [ 8 | 'webpack-dev-server/client?http://localhost:8080', 9 | 'webpack/hot/dev-server', 10 | './src/index' 11 | ], 12 | output: { 13 | path: path.join(__dirname, 'dist'), 14 | filename: 'bundle.js' 15 | }, 16 | plugins: [ 17 | new webpack.HotModuleReplacementPlugin(), 18 | new HtmlWebpackPlugin({ 19 | template: './src/index.html' 20 | }) 21 | ], 22 | module: { 23 | loaders: [{ 24 | test: /\.css$/, 25 | loaders: ['style', 'css'] 26 | }] 27 | }, 28 | devServer: { 29 | contentBase: './dist', 30 | hot: true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /zh-TW/part1/css-extract/webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | var HtmlWebpackPlugin = require('html-webpack-plugin') 4 | var ExtractTextPlugin = require("extract-text-webpack-plugin"); 5 | 6 | module.exports = { 7 | devtool: 'source-map', 8 | entry: ['./src/index'], 9 | output: { 10 | path: path.join(__dirname, 'dist'), 11 | filename: 'bundle.js' 12 | }, 13 | plugins: [ 14 | new webpack.optimize.UglifyJsPlugin({ 15 | compressor: { 16 | warnings: false, 17 | }, 18 | }), 19 | new webpack.optimize.OccurrenceOrderPlugin(), 20 | new HtmlWebpackPlugin({ 21 | template: './src/index.html' 22 | }), 23 | new ExtractTextPlugin("styles.css") 24 | ], 25 | module: { 26 | loaders: [{ 27 | test: /\.css$/, 28 | loader: ExtractTextPlugin.extract("style-loader", "css-loader") 29 | }] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /zh-TW/part1/example1/README.md: -------------------------------------------------------------------------------- 1 | # 範例一 - Bundle 和 Loader 2 | 3 | ![Official Dependency Tree](http://i.imgur.com/YU4xBPQ.png) 4 | 5 | Webpack 簡稱為模組的整合工具。如果你想要深入的話,可以拜訪「modules」和「module bundling definitely」這兩篇優秀的解釋文章: 6 | [JavaScript Modules: A Beginner’s Guide](https://medium.freecodecamp.com/javascript-modules-a-beginner-s-guide-783f7d7a5fcc#.jw1txw6uh) 7 | 和 [JavaScript Modules Part 2: Module Bundling](https://medium.com/@preethikasireddy/javascript-modules-part-2-module-bundling-5020383cf306#.lfnspler2)。 8 | 我們要保持它的簡單,webpack 運作的方式是透過指定一個單一檔案作為你的進入點。 9 | 這個檔案會是 tree 的 root。然後你每次 `require` 一個檔案從其他檔案並把它加入到 tree。當你執行 `webpack`,所有的檔案和 module 都會被 bundle 成一個檔案。 10 | 11 | 這裡是一個簡單的範例: 12 | 13 | ![Dependency Tree](http://i.imgur.com/dSghwwL.png) 14 | 15 | 根據這樣的情況,你可以有這樣的目錄: 16 | 17 | ``` 18 | MyDirectory 19 | |- index.js 20 | |- UIStuff.js 21 | |- APIStuff.js 22 | |- styles.css 23 | |- extraFile.js 24 | ``` 25 | 26 | 這些可能是你檔案的內容: 27 | 28 | ```javascript 29 | // index.js 30 | require('./styles.css') 31 | require('./UIStuff.js') 32 | require('./APIStuff.js') 33 | 34 | // UIStuff.js 35 | var React = require('React') 36 | React.createClass({ 37 | // stuff 38 | }) 39 | 40 | // APIStuff.js 41 | var fetch = require('fetch') // fetch polyfill 42 | fetch('https://google.com') 43 | ``` 44 | 45 | ```css 46 | /* styles.css */ 47 | body { 48 | background-color: rgb(200, 56, 97); 49 | } 50 | ``` 51 | 52 | 當你執行 `webpack`,你會得到一個這個 tree 的 bundle 內容,雖然 `extraFile.js` 也是在相同的目錄中,但它不是被 bundle 的一部份,因為它在 `index.js` 沒有被 `require`。 53 | 54 | `bundle.js` 看起來會像: 55 | 56 | ```javascript 57 | // contents of styles.css 58 | // contents of UIStuff.js + React 59 | // contents of APIStuff.js + fetch 60 | ``` 61 | 62 | 被 bundle 的這些檔案是你明確所 require 進來的檔案。 63 | 64 | ### Loaders 65 | 66 | 你可能會注意到,我在上方的範例做了一些奇怪的事情。我在 JavaScript 檔案中 `require` 一個 css 檔案。 67 | 68 | 關於 webpack 真的很酷,有趣的事情是,你可以 `require` 其他不只是 JavaScript 的檔案。 69 | 70 | 在 webpack 這些東西我們稱為 loader。使用這些 loader,你可以 `require` 任何 `.css` 和 `.png` 到 `.html` 檔。 71 | 72 | 例如在上圖我有: 73 | 74 | ```javascript 75 | // index.js 76 | require('./styles.css') 77 | ``` 78 | 79 | 如果在我的 webpack 設定檔中,inclue [style-loader](https://github.com/webpack/style-loader) 和 [css-loader](https://github.com/webpack/css-loader),這是可行的,還可以實際應用 CSS 到我的網頁。 80 | 81 | 你可以在 webpack 使用多個 loader,這裡只是一個單一的例子。 82 | -------------------------------------------------------------------------------- /zh-TW/part1/example1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example1", 3 | "version": "1.0.0", 4 | "description": "![Official Dependency Tree](http://i.imgur.com/YU4xBPQ.png)", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "fetch": "^1.0.0", 14 | "react": "^0.14.7" 15 | }, 16 | "devDependencies": { 17 | "css-loader": "^0.23.1", 18 | "style-loader": "^0.13.0", 19 | "webpack": "^1.12.14" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /zh-TW/part1/example1/src/APIStuff.js: -------------------------------------------------------------------------------- 1 | var fetch = require('fetch') // fetch polyfill 2 | fetch('https://google.com') 3 | -------------------------------------------------------------------------------- /zh-TW/part1/example1/src/UIStuff.js: -------------------------------------------------------------------------------- 1 | var React = require('React') 2 | React.createClass({ 3 | // stuff 4 | }) 5 | -------------------------------------------------------------------------------- /zh-TW/part1/example1/src/extraFile.js: -------------------------------------------------------------------------------- 1 | console.log('No one likes me') 2 | -------------------------------------------------------------------------------- /zh-TW/part1/example1/src/index.js: -------------------------------------------------------------------------------- 1 | require('./styles.css') 2 | require('./UIStuff.js') 3 | require('./APIStuff.js') 4 | -------------------------------------------------------------------------------- /zh-TW/part1/example1/src/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: rgb(200, 56, 97); 3 | } 4 | -------------------------------------------------------------------------------- /zh-TW/part1/example1/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: ['./src/index'], // .js after index is optional 6 | output: { 7 | path: path.join(__dirname, 'dist'), 8 | filename: 'bundle.js' 9 | }, 10 | plugins: [ 11 | new webpack.optimize.UglifyJsPlugin({ 12 | compressor: { 13 | warnings: false, 14 | }, 15 | }), 16 | new webpack.optimize.OccurrenceOrderPlugin() 17 | ], 18 | module: { 19 | loaders: [{ 20 | test: /\.css$/, 21 | loaders: ['style', 'css'] 22 | }] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /zh-TW/part1/example2/README.md: -------------------------------------------------------------------------------- 1 | # 範例二 - 一個簡單的範例 2 | 3 | 你的目錄結構像是這樣: 4 | 5 | ``` 6 | MyDirectory 7 | |- dist 8 | |- src 9 | |- index.js 10 | |- webpack.config.js 11 | 12 | ``` 13 | 14 | 然後這是一個非常簡易的 webpack 設定: 15 | 16 | ```javascript 17 | // webpack.config.js 18 | var path = require('path') 19 | 20 | module.exports = { 21 | entry: ['./src/index'], // .js after index is optional 22 | output: { 23 | path: path.join(__dirname, 'dist'), 24 | filename: 'bundle.js' 25 | } 26 | } 27 | ``` 28 | 29 | 我們一個一個複習這些屬性: 30 | 31 | * [entry](https://webpack.github.io/docs/configuration.html#entry) - 這是你的 bundle 的進入點,這是我們在討論 [bundling](#bundling) 的部分。`entry` 是一個陣列,根據你的需求,webpack 允許可以有多個進入點,來產生多個 bundle 檔案。 32 | 33 | * [output](https://webpack.github.io/docs/configuration.html#output) - 由 webpack 規定的形式輸出。 34 | * [path](https://webpack.github.io/docs/configuration.html#output-path) - bundle 檔案位置。 35 | * [filename](https://webpack.github.io/docs/configuration.html#output-filename) - bundle 檔案名稱。 36 | 37 | 當你執行 `webpack`,會在你的 dist 資料夾建立一個叫做 `bundle.js` 的檔案。 38 | -------------------------------------------------------------------------------- /zh-TW/part1/example2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example2", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "webpack.config.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "MIT" 12 | } 13 | -------------------------------------------------------------------------------- /zh-TW/part1/example2/src/index.js: -------------------------------------------------------------------------------- 1 | console.log('It works!') 2 | -------------------------------------------------------------------------------- /zh-TW/part1/example2/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | 3 | module.exports = { 4 | entry: ['./src/index'], // .js after index is optional 5 | output: { 6 | path: path.join(__dirname, 'dist'), 7 | filename: 'bundle.js' 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /zh-TW/part1/example3/README.md: -------------------------------------------------------------------------------- 1 | # 範例三 - 介紹 Plugins 2 | 3 | 想像一下,你使用 webpack 將你的檔案 bundle 在一起,然後你發現到 bundle 後的結果是 900KB。這裡有個問題,但是你可以透過 minify 你的 bundle 檔案來做改善。如果需要做到這一點,你需要使用一個我在前面稍早提到的 [UglifyJsPlugin](https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin) plugin。 4 | 5 | 此外,你需要在本機安裝 webpack 才能實際的去使用這個 plugin。 6 | 7 | npm install --save-dev webpack 8 | 9 | 現在你可以 require webpack 並 minify 你的程式碼。 10 | 11 | ```javascript 12 | // webpack.config.js 13 | var path = require('path') 14 | var webpack = require('webpack') 15 | 16 | module.exports = { 17 | entry: ['./src/index'], 18 | output: { 19 | path: path.join(__dirname, 'dist'), 20 | filename: 'bundle.js' 21 | }, 22 | 23 | plugins: [ 24 | new webpack.optimize.UglifyJsPlugin({ 25 | compressor: { 26 | warnings: false, 27 | }, 28 | }) 29 | ] 30 | } 31 | ``` 32 | 我們一個一個複習這些屬性: 33 | 34 | * plugins - 一個可以儲存你的 plugin 的陣列。 35 | * [webpack.optimize.UglifyJsPlugin](https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin) - Minify 你的程式碼,並顯示警告訊息。 36 | 37 | 這個時候,當我們執行 `webpack`,`UglifyJsPlugin` 通過像是移除所有空白的處理,可以將你的檔案減少至 200KB。 38 | 39 | 你也可以加入 [OccurenceOrderPlugin](https://webpack.github.io/docs/list-of-plugins.html#occurrenceorderplugin)。 40 | 41 | > 透過發生次數分配 module 和 chunk 的 id。一些常用的 Id 取得較低(短)的 id。這使得 id 可以預測,減少檔案的大小和建議。 42 | 43 | 老實說,我不太確定底層的機制是如何工作的,但在目前包含 [webpack2 beta 的預設情況下](https://gist.github.com/sokra/27b24881210b56bbaff7),所以我將它包含在內。 44 | 45 | ```javascript 46 | // webpack.config.js 47 | var path = require('path') 48 | var webpack = require('webpack') 49 | 50 | module.exports = { 51 | entry: ['./src/index'], 52 | output: { 53 | path: path.join(__dirname, 'dist'), 54 | filename: 'bundle.js' 55 | }, 56 | plugins: [ 57 | new webpack.optimize.UglifyJsPlugin({ 58 | compressor: { 59 | warnings: false, 60 | }, 61 | }), 62 | new webpack.optimize.OccurenceOrderPlugin() 63 | ] 64 | } 65 | ``` 66 | 67 | 所以現在我們寫了一個設定檔讓我們可以 minify 和 bundle 我們的 JavaScript。這個 bundle 檔案可以被複製並貼到其他的專案目錄中,放入 `