Background
Remember 2004, the Internet development is to do Web pages, there is no front-end and back-end of the distinction, sometimes a site is some pure static HTML, through the link organized together. Making a Web page is just like editing a document with world, except that the tool is called Dreamweaver. An HTML page, mixed with Css,javascript, is a common thing.
With the development of the front-end, especially the rise of single page application, this WYSIWYG IDE tool gradually exits the mainstream of the front-end. An application, usually only a static page (index.html), even the body of this page is composed of only one or a few div. There is a lot of CSS and JavaScript code to write. How to organize them is the problem that faces and solves at the front end now.
Some good front-end frameworks (like Angularjs,react,vue) can help us organize the code reasonably, maintaining the maintainability and extensibility of the code. This is useful in the development phase, but to publish the application to the line, you need to merge the code to reduce the size of the code, and the number of files, artificial code to be smeared. So there is the grunt,gulp,webpack and other front-end engineering packaging tools.
How to use Webpack
Before using Webpack, you need to install node. js and then install Webpack via NPM. Specific installation process to the official website. Take a look at one of the simplest applications in the order of entry and mastery.
Scenario One:
In the Demo1 directory, there are two files, app.js,cats.js, which need to be merged into a bundle.js file. Demo01
Cats.js:
var cats = [' Dave ', ' Henry ', ' martha '];module.exports = cats;
App.js:
Cats = require ('./cats.js '); Console.log (cats);
If the Webpack is installed globally, you can enter Webpack app.js bundle.js directly in the Command line window:
It's also easy to get a compact version, with a-p parameter appended to it:
The bundle.js from the original 1.58kb reduced to 304b.
If you don't want to lose the command at the command line every time you change it, hit enter once, just append a "-w" parameter (watch) to monitor the code.
Webpack App.js Bundle.js-p-W
Note: In this way, remove the Webpack.config.js file from the directory.
Although simple, there is an important concept here: The Official document app.js this file as the "entry point", or "portal". Represents where the webpack began. Webpack will follow this portal file to automatically find the files that are dependent on it, such as demo01 in the cats.js will automatically be loaded. And Bundle.js is the file name that we output after we specify the package, the default output directory is the directory where the command is run, or you can specify the output directory, such as./dist/bundle.js, so that Webpack automatically creates the Dist directory. Then write the bundle.js in the Dist directory. Because app.js this entry file is pure Js,webpack directly can support, if it is other types of files, such as CSS, you need to use "loader", that is, "loader", will be described in detail later.
In addition to specifying the portal file package directly with the Webpack command, you can also configure the Webpack.config.js file to achieve the same functionality:
Webpack.config.js:
Simplest Webpack Configuration Module.exports = { entry: './app.js ',//import file address output: { filename: ' bundle.js ',//file name after packaging
After configuring Webpack.config.js, you can simply enter webpack on the command line. If it is such a simple application, obviously does not show the value of Webpack.config.js existence. Usually our site will have a number of pages, such as Index,home,about, and so on, each page is a separate entrance, so there is a multi-entry situation, the following look at the multi-entry situation, webpack how to output different packaging files. Demo02
webpack.config.js//Multi-entry Example Module.exports = { entry: { bundle1: './main1.js ',//ENTRY 1 bundle2: './main2.js ' Entry 2 }, output: { filename: ' [name].js '//[name] is a variable that is automatically replaced with entry key }};
Compared to demo01, this time the entry (entry) is an object that specifies multiple entry files in the form of a key-value pair, and the output file name is represented by a variable. In fact, the value of the portal file can also be an array. Such as:
webpack.config.js//Multi-entry Example Module.exports = { entry: { bundle1: ['./main1.js '],//ENTRY 1 bundle2: ['./ Main2.js ']//entry 2 }, output: { filename: ' [name].js '//[name] is a variable that is automatically replaced with the entry key }};
This usage is useful for importing files that require more than one type of file to be specified. For example, ['./main1.js ', './main1.css '], followed by the finer words. To summarize: For entry there are altogether three forms:
1. Entry: ' App.js ' Write the entry file directly
2. Entry:{bundle: './main1.js '} object form
3. The values in the entry:{bundle:['./main1.js '} object are represented by an array
The next demo03 will show the usage of Webpack in Jsx, Es6. This section will be a little bit more. The first is the Package.json file, which is not part of the webpack, but often and Webpack project double-entry pair, first look at its approximate appearance:
{ "name": "Demo01", "version": "1.0.0", "description": "Sample to use Webpack", "main": "Index.html", "Scripts": { "test": "Echo \" Error:no test specified\ "&& exit 1", "Start": "Webpack" }, " Keywords ": [ " Webpack " ], " author ":" Frog ", " license ":" MIT ",
"Dependencies": {}, "Devdependencies": { "Babel-core": "^6.20.0", "Babel-loader": "^6.2.10", " babel-preset-es2015 ":" ^6.18.0 ", " babel-preset-react ":" ^6.16.0 ", " react ":" ^15.4.1 ", " React-dom ": "^15.4.1", "Webpack": "^1.13.0" }}
For more information about this document, please visit the official content here I would only highlight the following content:
1. The scripts command-line script is described in key:value manner. Key is the script name, and value is what the script executes, which can be performed by entering the NPM run script name on the command line. This piece of content is practical development is very practical, here is not detailed expansion, reference address
Common script names are: NPM run start, NPM run test. The built-in script name (for example, start) can omit run.
2. Devdependencies development dependency, corresponding to a dependencies (can be understood as production environment dependence)
Via NPM Install package name--save-dev (save to Devdependencies), or--save save to (dependencies)
Package.json is used to manage and release packages, and if you don't want to publish the project, it seems that the above is not good for project development, but as a team, it makes it easy for you and your colleagues to quickly build projects and manage the third-party packages used in your projects.
Go back to the Webpack.config.js file below. Since JSX is a react dedicated syntax, beyond the syntax of JS, to load JSX files, you need a loader (loader), different types of files have different loaders, such as jsx,es6 to use Babel-loader
Loading CSS to use Css-loader, loading HTML to use Html-loader and so on. Here are the specific uses:
Module.exports = { entry: './main.jsx ', output: { filename: ' Bundle.js ' }, module: { loaders : [ { test:/\.js[x]?$/, exclude:/node_modules/, loader: ' Babel-loader ', query:{ presets:[' react ', ' es2015 '} } , ]} };
All the loader are placed in the loaders below the module. Usually the following:
1. Test: is a regular expression of this type of file, used to determine the conditions for using this loader.
2. Exclude is the excluded directory, such as node_modules files, usually compiled JS, can be directly loaded, so in order to optimize the speed of packaging can be excluded. As an optimization means it is not necessary.
3. Loader: The name of the loader, each loader has its own usage, specifically to refer to the official note.
4. Query: Additional parameters or configuration information passed to the loader, and some can be configured separately by generating special files in the root directory, such as. BABELRC
Configuration here, not yet, you need to install the corresponding loader to the project, the installation is very simple, through the command line, enter the name of the NPM install loader--save-dev or--save
The purpose of adding--save or--save-dev is to record the plugin in Package.json, which is easy to install automatically when using NPM install.
When installed through the npm3.0+ version, it will not automatically install dependencies and need to be installed manually, such as when installing this babel-loader, it prompts to install Babel-core and Webpack, and then install. demo03 more radical, directly with the JSX and ES6 syntax, so to install more plug-ins, but this is also the actual development of often used.
"Devdependencies": { "Babel-core": "^6.20.0", "Babel-loader": "^6.2.10", "babel-preset-es2015": "^ 6.18.0 ",//es6 to ordinary JS with " babel-preset-react ":" ^6.16.0 ",//Parse jsx with " react ":" ^15.4.1 ", " react-dom ":" ^ 15.4.1 ", " Webpack ":" ^1.13.0 " }
Since we added a start script to Package.json's script, this time, I'm not going to use the old fashioned, this time to try something fresh. Run NPM start directly to see if there is a miracle.
This is the same result as running Webpack directly, but it looks taller. If half of you will not feel the react or es6 so trendy, then please ignore the previous content, see a little more simple and more common loader
DEMO04 Css-loader Style Loader
Module.exports = { entry: './main.js ', output: { filename: ' Bundle.js ' }, module: { loaders: [ {test:/\.css$/, Loader: ' Style-loader!css-loader '}, ]} ;
Here are two places to note:
1. For cases in which multiple loaders are concatenated, Webpack is loaded from right-to-left dependencies, that is, using Css-loader first, and then using Style-loader.
2. Why there is a style-loader, because Webpack by default is the CSS file inserted in the HTML file, through the style tag loaded styles. So you need to use style-loader this loader.
If you want to put CSS in the form of a file link to HTML, it is also possible, later on.
Since we used the CSS loader, the entry file can actually be written directly: entry: './app.css '; The effect is the same. This shows that the entry file, not necessarily the JS format, as long as there is a corresponding loader, you can use directly in the portal, and even a variety of types of mixed use, such as ['./app.js ', ' app.css '], are OK.
In style, images are often used, such as Background:url ('. /images/logo.jpg '); If you do not specify the loader, you will get an error (may need a appropriate loader to handle this file type), at this time, you need to use the picture loader, do not think, only in the portal used in the file to the loader, As long as the file is loaded during webpack work, as long as it is not a JS file, you need to specify the loader and configure it correctly in Webpack.config.js.
Module.exports = { entry: './main.js ', output: { filename: ' Bundle.js ' }, module: { loaders: [ {test:/\. ( png|jpg) $/, loader: ' Url-loader?limit=8192&name=[name][ext] '} } };
The picture loading-demo05 example uses Url-loader, not the desired image-loader, because Url-loader can load the files of the picture font, so there is no need to reinvent the wheel, in fact, Url-loader is not the final loader, It is merely a further encapsulation of the file-loader. By mounting more configuration parameters behind the Url-loader, you can achieve customized requirements, such as images smaller than 8192 bytes, in the form of Base64, and direct output in CSS to reduce HTTP requests. For large images with this restriction, the name of the output is specified by name, and the path specified above is also possible. For example/images/[name][ext], where [name] and [ext] are the representations of variables, as mentioned earlier, used here, indicating the original input with the file name and extension. It is important to note that this path is the reference to the default output path. What if you want to specify the output path?
Please refer to the following methods:
1. By specifying in Webpack.config.js, Output:{path: './dist ',...}
Module.exports = { entry: './src/app.js ', output: { path: './dist ',//new output path filename: ' App.bundle.js '} };
'./' represents the current directory of the project, usually refers to the root directory, which is a representation of a relative path, or can be specified with an absolute path through Path.resolve (__dirname, './'), at which point the Js,css file generated by Webpack becomes. Dist directory, and for the picture in this example, in the./directory,
Did not generate the picture in the Dist directory, try loader: ' url?publicpath=./dist/'
Module.exports = { entry: ['./main.js ', './icon.css '], output: { path: './dist ', filename: ' Bundle.js ' }, module: { loaders:[ {test:/\. ( png|jpg) $/, loader: ' url-loader?limit=8192&publicpath=./dist/'}, {test:/\.css$/, loader: ' style-loader! Css-loader '}, ]} ;
By specifying this publicpath implements the image generation to the specified directory. Similarly, specifying this value in output is the same thing.
Output: { path: './dist ', publicpath: './dist/',//here Specifies the same effect as filename: ' Bundle.js ' },
This publicpath was originally used to configure the virtual directory, that is, when the path is accessed via HTTP, or when the output directory is loaded by Webpack HMR mode. It can only be regarded as a hack usage here. When it comes to output, mention the use of the file cache [hash]:
Output: { path: './dist ', publicpath: './dist/', filename: ' bundle_[hash:8].js '//By: 8 intercept the first 8 bits of the has value },
This [hash] practice is rarely mentioned, in the actual development, is a very common function, the original output of the hash I feel too long, can be [hash: plus the number] way to intercept, very convenient.
For Webpack.config.js, the above has introduced the Entry,output,module, the following code for example, to say Plugins,webpack plug-in usage: demo07
var webpack = require (' Webpack '); var uglifyjsplugin = Webpack.optimize.uglifyjsplugin;module.exports = { entry: './ Main.js ', output: { filename: ' Bundle.js ' }, plugins: [ new Uglifyjsplugin ({ compress: { Warnings:false } }) ]}
Plugins: The value is an array, all plugins are installed through NPM install, and then add the corresponding plug-in configuration in the plugins array. There are three plugins that need to be mentioned:
1. Htmlwebpackplugin This plugin can insert the generated CSS, JS into the HTML page head,body, which is useful for adding the hash value of the output. This function can also be done with Gulp's Insject plugin. However, since the use of webpack, and temporarily forget the Gulp bar. It's not a good idea to switch between different tools with similar features. However, the HTML plugin has a small problem, it does not parse the HTML in the same way as the IMG in CSS. caused the HTML file under the Dist directory, the SRC error under IMG. The workaround is to add Html-withimg-loader to this plugin.
{ test:/.html$/, loader: ' Html-withimg-loader?min=false ' },
2. Commonschunkplugin extract the public code, this does not need to install, Webpack integration has.
New Webpack.optimize.CommonsChunkPlugin ({ name: ' Vendor ', filename: ' js/vendor.js ', chunks:[' Chunk1 ', ' Chunk2 ', ' Chunk3 ']//not written for all the chunk, }),
Chunk (block), another very important concept in Webpack, corresponds to entry. There are three types of cases:
2.1 If entry is specified through a string, then chunk refers to the entry file, such as entry: './app.js '; Then be sure chunk and './app.js ' one by one correspond.
2.2 If it is entry:['./app1.js ', ' app2.js ', then chunk is the sum of these two files.
* the chunk [name] above is the default "main".
2.3 If this is the following form:
entry:{ index: './index.js ', error: './error.js ', vendor:[' react ', ' Redux ']}
Then there will be multiple chunk,[name] respectively and Index,error,vendor corresponding.
3. Extracttextplugin This plugin is the plug-in that separates the CSS from the HTML at the beginning. NPM Install Extract-text-webpack-plugin--save-dev
Plugins: [ New Extracttextplugin ("[name].css"),]
It is important to note that if you add a subpath in front of [name].css, such as CSS/[NAME].CSS, you should be careful about the picture path in the style, especially if you do not specify Publicpah. Background:url (the picture of this place by default is the same as the output path of the chunk, if the Publicpath is specified, then Publicpath instead, there is no problem), but because we have to specify the packaging after the style is placed in the css/directory, The image is still in the original directory, which causes the image path referenced in the CSS to be invalidated. Look at the following example:
var extracttextplugin = require ("Extract-text-webpack-plugin"); module.exports = { entry: ['./main.js ', './ Icon.css '], output: { path: './dist ', //publicpath: './dist/', filename: ' bundle_[hash:8].js ' }, module: { loaders:[ {test:/\. png|jpg) $/, loader: ' url-loader?limit=8192 '}, {test:/\.css$/, loader:ExtractTextPlugin.extract (' style ', ' CSS ') }, ]} , plugins: [ new Extracttextplugin ("Css/[name].css"), ]};
As you can see from the diagram, after adding a CSS subdirectory, the image in the style is still the original path, and the picture does not exist in the CSS directory.
Workaround, either do not add subdirectories, keep style files and picture files always at the same level, or add publicpath, equivalent to using absolute paths. Since this is configured in the Webpack.config.js, it is easy to replace it.
Everything looks good, but when we use the IMG tag in HTML, the problem comes, remember html-withimg-loader this plugin? It is also called Url-loader, so the final picture output path is also affected by Publicpath. Consider such a directory structure:
The style file is in the CSS subdirectory, and the HTML is maintained at the same level as the picture. The picture in the style needs to be specified as ".. /", and images in HTML need to be designated as"./", which in the same publicpath, the display is conflicting. At this point, it is necessary to weigh, either all the files are stacked in the root directory, or the HTML images are processed with other plugins. In short, this conflict cannot be allowed to happen.
Summary
Originally also want to write Webpack hot load HMR, and Webpack-dev-server,browser-sync combined with webpack usage, feel to write a bit more content, these content is also practical development of very useful technology. The more you write to the back, the more difficult it is. Think of a word, want to give someone a drop of water, they must have at least a bucket. Front-end Project Automation program updated quickly, Webpack has not come to the very popular, webpack2,rollup and so forth. Learning these tools is to reduce duplication of effort and improve efficiency. Choose a solution that suits you, rather than losing your way in the pursuit of technology.
The front-end automation packaging tool--webpack