myJS
  • 说明
  • js核心
  • 函数式编程
    • 链式优化
    • 你真的知道函数吗?
    • 纯函数
    • 函数柯里化
  • 内存的那些事
    • 栈内存和堆内存
    • 垃圾回收机制-GC
    • 闭包恍然大悟
      • 运行时的词法作用域
    • 数据结构基于内存
    • 怎样用chrome devtool 查看内存泄漏状况
    • dom元素的内存泄漏例子讲解
  • 网络请求
    • 原生js请求
    • https了解一下
    • 跨域方法
    • 你不知道的浏览器页面渲染机制
    • 聊点 TCP 干货(1)
  • 异步编程
    • await 和 async
  • 服务器
    • nginx
  • 模块化编程
    • commonJs模块
    • ES模块
    • AMD模块
    • CMD模块
    • module.exports与export那些事儿
  • webpack
    • 环境变量的使用
      • node配置
      • webapck配置
    • postcss处理css
    • webpack-dev-server
    • HMR热更新原理
    • babel配置
      • 转化es6
      • Runtime transform/runtime
    • extract-text-webpack-plugin
    • css加载
    • 打包优化
    • 第三方插件加载中
    • 热更新踩坑
    • typescript+node
    • 代码分割的意思
  • CMD命令行
    • 文件的增删改查
  • node
    • path模块
    • node 文件路径的分析
  • js一些资源库
  • node毛皮
    • cnpm 淘宝镜像
  • 浏览器调试
    • js调试
    • 浏览器同源政策及其规避方法
  • 好好理解变量
    • this指向
    • 作用域
  • 专有名词理解
    • MVC
  • postman
    • 环境变量
  • 树的遍历和操作
    • 二叉树
  • 关于Date你要知道的是?
    • 获取某个月的天数
    • js 日期详解
  • Dom 对象
  • 回调函数
    • 语法。为什么要用
  • class 怎样用好类
    • 用类直接创建对象关联到变量
  • js引擎
  • git操作
    • .gitignore忽略文件
    • 删除操作
  • table学习
    • 表格样式
    • 固定列和行
  • 拖拽
    • 目标容器
    • 狐火的拖拽就是不一样
  • 正则学习
  • 算法
    • 数据结构
  • js小技巧
  • indexDB
  • Matrix 矩阵
Powered by GitBook
On this page

Was this helpful?

  1. webpack

打包优化

Previouscss加载Next第三方插件加载中

Last updated 6 years ago

Was this helpful?

  • js 压缩优化 ,使用多线程的 webpack-parallel-uglify-plugin ,具体的参数配置可以看

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 ,在运行就可以了。接着又打开clean-webpack-plugin ,不报错了。搞不懂!!!

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

  • 第三方库的抽离,在webpack4.x之前是使用的 webpack.optimize.CommonsChunkPlugin ,来抽取公共的代码和分离第三方的代码,具体可以看,不过webapck4.x,已经弃用这个插件了,改为 optimization.splitChunks 和 optimization.splitChunks ,其中 optimization.splitChunks 选项里webpack会添加一个只包含运行时(runtime)额外代码块到每一个入口。(这个需要看场景使用,会导致每个入口都加载多一份运行时代码)

    //  抽离第三方的代码,也就是生产依赖里的代码,现在是单文件的入口:
           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让这两个文件引用,这样减少代码的重复。

// 抽离第三方的代码,也就是生产依赖里的代码,现在是单文件的入口:
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

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


)

按需加载 在webpack 的文件输出配置output中加上按需加载生成js 文件的配置 chunkname ,关于filename 与 chunkname 的理解可以看 。按需加载是需要搭配js文件里的代码使用的,光设置webpack是什么效果都没有的。拿react的路由做例子,在每一个路由点击的时候加载对应的组件。

react 配置 : 在react-router4后不再通过 getComponent来按需加载路由组件,通过bundle-loader更加简化了按需加载。安装 bundle-loader --save-dev 参考文件

https://github.com/mishoo/UglifyJS2/tree/harmony#compress-options
https://blog.csdn.net/github_26672553/article/details/52280655
https://segmentfault.com/a/1190000013476837
https://www.jianshu.com/p/d9ebab57bca1
https://www.vanadis.cn/2017/08/05/react-router-webpack-load-on-demand/