Say in front
Due to the use of react straight out, the page performance indicators make people pleasing. This article will delve into the current Webpack packaging optimization strategy used by PC tribes and explore the Webpack code splitting, asynchronous module loading features not used by PC tribes. See how they can play a further role in the performance of PC tribes.
Why to use Webpack
If you have ever used broserify, requirejs or similar packaging tools, and focus on: Code subcontracting, asynchronous loading, static resource packaging (picture/css). Then Webpack is the tool to help you build your project! Simple sentence: In Webpack, all resources are considered as modules, JS can be referenced css, CSS can be embedded in the image dataurl.
Webpack characteristics
For different file types of resources, Webpack has the corresponding module loader, for example, for less, less-loader you can find all the loader here. Webpack has Requirejs and browserify features, but still has its own new features : 1, to CommonJS, AMD, ES6 of the syntax of the compatibility; 2, the JS, CSS, pictures and other resource files support packaging, 3, the series module loader and plug-in mechanism for better flexibility and scalability, such as the Coffeescript, ES6 support; 4, There is a separate configuration file webpack.config.js; 5, the code can be cut into different chunk, to achieve on-demand loading, reduce the initialization time, 6, support Sourceurls and Sourcemaps, easy to debug, 7, with a strong Plugin interface, mostly internal plug-ins, use more flexible; 8, Webpack Using asynchronous IO with multi-level caching makes the Webpack faster on incremental compilation!
Why Mix grunt and Webpack?
Since the birth of React, it has been well known that React+webpack has developed Dafa, and in most React Web tutorials It is seldom mentioned that Grunt co-construction projects are used simultaneously.
Grunt can copy, delete, merge, compress, and so on throughout the project file. The advantage of Webpack is that static files (js/jsx/coffeescript/css/less/sass/iamges) are loaded in different modules (including on-demand loading)-and that's where we're interested in Webpack, Each module is organized (you can put a set of pictures, styles, scripts, pages in the same folder). Therefore, in the project of the two different division of duties, each.
Note: replacing grunt with Gulp is certainly not a problem.
Webpack Configuration
Webpack has a variety of configuration methods, because the PC tribe of static resources files, using the configuration file for packaging is much easier.
Typically, if we build a project using only Webpack, we can configure Webpack.config.js. Due to the use of grunt in the PC tribe and the invocation of Webpack tasks in the grunt composition task, it is necessary to add webpack.js (plug-in) configuration in the Grunt task configuration load-grunt-config .
Configuration Overview
var taskconfig = {dev: {entry: {Portal file, considering the multi-page resource cache, we make multiple packages"Index": Path.resolve (Config.srcpath,"Pages/index/index.jsx"),"Detail": Path.resolve (Config.srcpath,"Pages/detail/detail.jsx"), ...}, resolve: {Request redirection, display indicates dependent lookup path alias: {img:path.resolve (Config.srcpath +' img '), Comps:path.resolve (Config.srcpath +' Pages/components ') ...} }, Output: {Output file Path:config.devPath +'/js ',File absolute path filename:"[Name].min.js",Output file name Publicpath:"Http://s.url.cn/qqun/xiaoqu/buluo/p/js/",Public access Path, replacing CDN Chunkfilename:"[Name].chunk.min.js]The file name} that needs to be packaged when loading asynchronouslyModule: {Various documents Loader Noparse: [],Ignore parsed file preloaders: [{Pre-loaded module test:/\.jsx$/, exclude:/node_modules/, Loader:' Jsxhint-loader '}], loaders: [{All kinds of loader test:/\.jsx$/, Loader:' Jsx-loader ', Include:path.resolve (Config.srcpath)}, {test:/\.less$/,Use "! "Chained loader, right-to-left execution loader:ExtractTextPlugin.extract ("Style-loader","Css-loader!less-loader"), Include:path.resolve (Config.srcpath)}, {test:/\. (jpe?g|png|gif|svg) $/i,Inline Base64url for <=1500 images loader:' Url-loader?limit=1500&name=images/[name]. [Hash]. [ext] ', Include:path.resolve (Config.srcpath)}]}, Externals: {//specifies resources that are dependent on an external CDN and are not webpack packaged "React", "React-dom": "ReactDOM"}, Plugins: [... //Public Module Standalone package configuration new commonschunkplugin ( "common", "Common.min.js", [ "index ", " search "] , //independently packaged CSS files outside the chain form load new extracttextplugin (". /css/[name].min.css ")], watch: true, KeepAlive: true, Lessloader: {lessplugins: [new Lesspluginautoprefix ()]}}, /span>
Webpack Package Optimization 1, request redirection
resolve.aliasis a configuration item for Webpack, which is the function of redirecting a user's request to another path. Like what:
resolve: { // 显示指出依赖查找路径 alias: { comps: ‘src/pages/components‘ }}
This is actually equivalent to the use of the script we want to package require(‘comps/Loading.jsx‘); require(‘src/pages/components/Loading.jsx‘) . This is like high-performance JavaScript gives an alias to the object with the higher pressure of the query, which can be reduced by almost half of the time by using an alias.
2. Ignoring the parsing of known files
module.noParse, if you determine that there are no other new dependencies in a module , you can configure this, and Webpack will no longer scan for dependencies in this file. For example entry.js , we detect requests for resource resources in the portal file src/pages/components/ueditor.min.js , if we configure:
module: { noParse: [/ueditor/]}
noParseOne of the rules is in /ueditor/ effect, so webpack directly packs the dependencies into it entry.js . Adding such a configuration will make the Webpack compile time shorter.
3. Use a public CDN
Considering that there are a lot of public CDN services on the Web, we can react separate them from bundles and not be packaged by Webpack as externally dependent reference CDN. method is to use externals declaring an external dependency. Such as:
module:{ externals: { // 方式一:申明为外部依赖并指定别名 "react": "React", "react-dom": "ReactDOM" // 方式二:true 为外部依赖,false 则不是 a: false, // a is not external b: true // b is external },}
and add a line to the HTML code
<script src="//cdn.bootcss.com/react/0.14.2/react.js"><script src="//cdn.bootcss.com/react/0.14.2/react-dom.js">
So we introduced in JS React = require(‘react‘) , Webpack will not put react packaged in and directly reference CDN, this can make webpack compile time reduced more than half!
Series Plug-in Commonschunkplugin
In the development, we need to package the common modules of multiple pages independently , so that we can use the browser caching mechanism to improve the efficiency of page loading, reduce the initial load time of the page, and only load dynamically when a function is used. This will use the Commonschunkplugin plugin in the Webpack.
Use:
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");module.exports = { ... /* * @param 1 将公共模块提取,生成名为 common 的chunk * @param 2 最终生成的公共模块的 js 文件名 * @param 3 公共模块提取的资源列表 */ new CommonsChunkPlugin("common", "common.min.js", ["index", "detail", "barindex", "search"])}
Extracttextplugin
When writing a JS file in Webpack, you can require introduce other static resources in a way that can automatically parse and package files by loader. Usually we will package the JS file merge, CSS file in the page header embedded style of the way to load the page. But in the development process We do not want to package the style in the script (it is best to independently generate CSS files, outside the chain to load). The Extracttextplugin plugin can help us achieve this effect.
Installation:
npm install extract-text-webpack-plugin –save-dev
Use:
var ExtractTextPlugin = require("extract-text-webpack-plugin");module.exports = { ... plugins: [ new ExtractTextPlugin("../css/[name].min.css") ]}
This allows the CSS file in JS to be extracted and loaded with the specified file name.
Lesspluginautoprefix
As the name implies, is the Autoprefix plug-in, used to complement the full CSS vendor prefix (-webkit-,-Moz-,-O);
Use:
var LessPluginAutoPrefix = require(‘less-plugin-autoprefix‘);var taskConfig = { dev: { ... lessLoader: { lessPlugins: [ new LessPluginAutoPrefix() ] } }
Code splitting
For a large web app, we have all the JS files to synthesize one is obviously very inefficient, because some JS module is not what we need on the current page (this will greatly increase the page first screen rendering time). Webpack is such an artifact, to provide you with high-quality code subcontracting services, from the "Mom no longer worry about the page loading problems on demand"!
Way one: Require
require(dependencies, callback)Follow the asynchronous methods defined by the AMD specification. When using this method, all dependencies are loaded asynchronously and executed immediately from left to right , and dependencies are executed after execution callback .
Way two: Require.ensure
require.ensure(dependencies, callback)Follow the CommonJS specification and download the dependent modules when needed. When all dependencies are loaded, execute callback (note: Require as the callback parameter). The attentive classmate may remember output that the configuration has
output: { ... chunkFilename: "[name].chunk.min.js"}
chunkWhat is it? chunkand how is it generated? In order to implement asynchronous loading of some resources, some resources are not packaged into the entry file. So we used require.ensure the identity that was split as code. require.ensurea chunk is created, and you can specify the name of the chunk (note: If the chunk already exists, the module that is dependent is merged into the existing chunk), and finally the chunk builds a separate file when the Webpack is built. For example, to load two different UI builds based on the current running platform, then:
var platform = Util.getplatform (); if (platform = = = " ios ") {require.ensure ([function ( Span class= "Hljs-params" >require) {...}, ' popup '); //last parameter is chunk name} if (platform = = "Android") { Require.ensure ([ function (require) {...}, ' popup ') ;}
After packaging through Webpack, a file is generated popup.chunk.min.js . On different operating platforms, we will find that the contents of the Popup.chuck.min.js file are the same (because the chunk name we configured is popup). If we want the load-on-demand module to be split into dialog and toast again, two files, just need to require.ensure change the chunk name in the configuration, and load a single file when the code is executed.
Note the point:
1, require : Load the module, and immediately execute; 2 require.ensure : Only load the module, but will not execute; 3, do not display the call generated chunk file in HTML, will be automatically called when loading on demand, 4, do not worry about the third-party library is repeatedly packaged problem, because we have used CommonsChunkPlugin Extract the public part.
Webpack Packing Advanced