> For the complete documentation index, see [llms.txt](https://sekin.gitbook.io/myjs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sekin.gitbook.io/myjs/webpack/da-bao-you-hua.md).

# 打包优化

* **js 压缩优化 ，使用多线程的 webpack-parallel-uglify-plugin ，具体的参数配置可以看**[**https://github.com/mishoo/UglifyJS2/tree/harmony#compress-options**](https://github.com/mishoo/UglifyJS2/tree/harmony#compress-options)

```javascript
new parallelUglifyPlugin({
    cacheDir: '.cache/',
    uglifyJS: {
        output: {
            comments: false, //false :关闭注释 

        },
        compress: {
            warnings: false,
            drop_console: true,
            collapse_vars: true,
            reduce_vars: true,
        },
    },
    sourceMap:true,// 开启sourcemap
})
```

注意：有的时候， 这个插件第一次运行的时候会报错，报不是空目录，可能是与删除dist目录的插件**clean-webpack-plugin** 有关，我现在也搞不清楚了，之前在配置的时候，总是报错，把 **webpack-parallel-uglify-plugin** 注释掉后就可以用了，今天我再运行**webpack-parallel-uglify-plugin** 时还是报错 ，我先关闭了**clean-webpack-plugin ，**&#x5728;运行就可以了。接着又打开**clean-webpack-plugin ，**&#x4E0D;报错了。搞不懂！！！

现在搞清楚了,第一次运行**webpack-parallel-uglify-plugin** 时不能让.cache(压缩缓存)有内容，必须是空的，或是没有这个目录

* **第三方库的抽离，在webpack4.x之前是使用的 webpack.optimize.CommonsChunkPlugin ,来抽取公共的代码和分离第三方的代码，具体可以看**[**https://blog.csdn.net/github\_26672553/article/details/52280655**](https://blog.csdn.net/github_26672553/article/details/52280655)**，不过webapck4.x，已经弃用这个插件了，改为 optimization.splitChunks 和 optimization.splitChunks ，其中 optimization.splitChunks 选项里webpack会添加一个只包含运行时(runtime)额外代码块到每一个入口。（这个需要看场景使用，会导致每个入口都加载多一份运行时代码）**[**https://segmentfault.com/a/1190000013476837**](https://segmentfault.com/a/1190000013476837)

```javascript
    //  抽离第三方的代码，也就是生产依赖里的代码,现在是单文件的入口：
           entry: {
                main: PATHS.app,
                //vender:["react","react-dom","antd"],//引用的第三方库
            },
            mode:"production",
            output: {
                path: PATHS.build,
                filename: filename,
                publicPath:PATHS.publicPath,
            },
            optimization: {
                runtimeChunk: {//包清单
                    name: "manifest"
                },
                splitChunks: { //拆分公共包
                    cacheGroups: {
                        vendor: {//第三方组件
                            test: /node_modules/,
                            chunks: "initial",
                            name: "vendor",
                            priority: 10,
                            enforce: true
                        }
                    }
                }

            },
```

* **有时需要多文件的入口，这对个文件里就肯定有相同额部分。比如 common.js 是个工具插件，a.js引用了common.js， b.js也引用了common.js。 当我们把a.js和b.js分别作为入口文件的时候，他们两个都加载了common.js，所以可以提供一个公共的js让这两个文件引用，这样减少代码的重复。**

```javascript
// 抽离第三方的代码，也就是生产依赖里的代码,现在是单文件的入口：
entry: {
    main: PATHS.main,
    home: PATHS.home,
    //vender:["react","react-dom","antd"], //引用的第三方库
},
mode:"production",
output: {
    path: PATHS.build,
    filename: filename,
    publicPath:PATHS.publicPath,
},
optimization: {
    runtimeChunk: {//包清单
        name: "manifest"
    },
    splitChunks: { //拆分公共包
        cacheGroups: {
            common: {//项目公共组件，多个入口文件可以用到
                chunks: "initial",//指定提取范围[],可以是所有"all"
                name: "common",//提取公共代码的js文件名
                minChunks: 2,//指定重复代码几次之后就提取出来 
                maxInitialRequests: 5,
                minSize: 0
            },
            vendor: {//第三方组件
                test: /node_modules/,
                chunks: "initial",
                name: "vendor",
                priority: 10,
                enforce: true
            }
        }
    }

},
```

* **静态资源拷贝插件 copy-webpack-plugin**&#x20;

```javascript
new copyWebpackPlugin([{
                from:__dirname+'/src/assert',//打包的静态资源目录地址
                to:'./assert' //打包到dist下面的public
}]),//拷贝静态资源到指定的位置，也就是不用编译这个目录下的文件
```

* **按需加载  在webpack 的文件输出配置output中加上按需加载生成js 文件的配置 &#x20;*****chunkname ,关于filename 与 chunkname 的理解可以看*** [***https://www.jianshu.com/p/d9ebab57bca1***](https://www.jianshu.com/p/d9ebab57bca1)**。按需加载是需要搭配js文件里的代码使用的，光设置webpack是什么效果都没有的。拿react的路由做例子，在每一个路由点击的时候加载对应的组件。**

```javascript
output: {
            path: PATHS.build,
            filename: "js/[name].min.js", // name 对应entry里的入口配置名
            publicPath:"./", 
            chunkFilename: 'js/[name].[chunkhash:5].chunk.js', // 生成对应额chunkhash加在文件名中 ，
            //name 对应 用 bundle-loader加载时设置额名字,看下面额例子
            //  import Apiopt from "bundle-laoder?lazy&name=apiopt!../containner/apiopt/apiopt.js"
},
```

**react** 配置 ： 在**react-router4**后不再通过 **getComponent**来按需加载路由组件，通过**bundle-loader**更加简化了按需加载。安装 **bundle-loader --save-dev 参考文件**[**https://www.vanadis.cn/2017/08/05/react-router-webpack-load-on-demand/**](https://www.vanadis.cn/2017/08/05/react-router-webpack-load-on-demand/)

```javascript
import React ,{Component} from  "react";
import { BrowserRouter ,HashRouter , Route ,Switch } from "react-router-dom";

import  {Home} from "../component/home.js";
import  ApiOpt from "bundle-loader?lazy&name=ApiOpt!../containner/apiopt/apiopt.js";
import  Application from "bundle-loader?lazy&name=Application!../containner/application/application.js";

class Bundle extends Componet {
    state={
        mod:null,
    }

    componentWillMound(){
        this.load(this.props);
    }

    componentWiillReciveProps(next,props){
         if (nextProps.load !== this.props.load) {
            this.load(nextProps)
        }
    }

    load(){
         this.setState({
            mod: null
        });

        // 这里的 props.load 是用  babel-loader 引入的异步加载函数，不是组件，是下面这样函数，参数是个回调函数
        //仔细看这个回调函数，发现它的参数才是真正的组件。使用 require()引入。
        // 所以这里又涉及到，我们在导出 模块时候是 怎么的方式。

         function(cb) {
            Promise.all(
                /*! require.ensure | Application */
                [__webpack_require__.e("vendors~ApiOpt~Application"),
                 __webpack_require__.e("vendors~Application"),
                 __webpack_require__.e("Application")]).then((function(require) {
                    cb(__webpack_require__(
                    /*! !../../../node_modules/_babel-loader@7.1.4@babel-loader/lib!./application.js */
                     "./node_modules/_babel-loader@7.1.4@babel-loader/lib/index.js!./src/containner/application/application.js"));
            }).bind(null, __webpack_require__)).catch(__webpack_require__.oe);
        }


        props.load((mod) => {
            this.setState({
                // handle both es imports and cjs
                mod: mod.default ? mod.default : mod 
                // 刚开始我不理解这个mod 是啥，现在很清楚了，是个用require 引入的模块
                // .default 是我们用的  export default 导出的。 所以 我们用require 时。 module 对象里的 key 值 default
                // 要是 我们用 export { } ，这里肯定就不能用default ,因为 module里的key 值就是我们当时定义的模块名
                // 然而我们最好使用 export default 导出  ，不然 不然在这个方法里不知道定义的模块名是什么。
            })
        })
    }

    render(){

        return this.props.children(this.state.mod); // 返回的是真正的组件

    }
}

const Loading=()=>{
    return (<div>Loading......</div>);
}


const createComponent = (component)=>{

        return (
            <Bundle load={component}>
                 (Component) => Component ? <Component {...props} /> : <Loading/>
            </Bundle>

        );
}

const Routes=(

    <Route path="./application"  component={createComponent(Appliction)} ></Route>
    <Route path="./apiopt" component={createComponent(ApiOpt)} ></Route>


)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sekin.gitbook.io/myjs/webpack/da-bao-you-hua.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
