美文网首页
webpack - 项目优化2

webpack - 项目优化2

作者: 我叫Aliya但是被占用了 | 来源:发表于2020-01-20 15:41 被阅读0次

    Webpack学习笔记
    webpack - 项目优化
    webpack实现原理
    webpack - loader
    webpack - plugin
    webpack - 项目优化2

    在production模式下,使用import导入的模块会自动shaking-tree,自动作用域提升

    node下使用chrome调试

    > node --inspect-brk ../mywebpack/bin/main.js
    ebugger listening on ws://127.0.0.1:9229/484e409c-5ae8-449a-b24a-9efb4db4f957
    For help, see: https://nodejs.org/en/docs/inspector
    

    在chrome中打开chrome://inspect/#devices

    点击inspect 可以使用chrome命中断点,进行逐步调试

    webpack-dev-server

    一个基于express的静态服务器,对打包后的文件热更新,方便调试

    可以webpack.config.js中添加配置

        // webpack-dev-server配置
        devServer: {
            port: 7070,
            contentBase: './dist'
        }
    

    webpack-dev-server启动调试

    eslint

    npm i eslint eslint-loader -D

    可以在 https://eslint.org/demo 配置配置文件(当然也可以自己写),下载下来的 eslintrc.config 重命名为.eslintrc.config

                {
                    test: /\.js$/,
                    use: {
                        loader: 'eslint-loader',
                        options: {
                            enforce: 'pre'  // 最先执行,post最后
                        }
                    }
                }
    

    入口文件中加一句let ttt = 9。打包后会提示:

    /Users/aliya/D/9200/08.02-mywebpack-test/index.js
      21:5  error  'ttt' is assigned a value but never used  no-unused-vars
    

    多入口,多出口

    const path = require('path') 
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    module.exports = {
        mode: 'development',
        entry: {
            home: './index.js',
            a: './common/a.js'
        },
        output: {
            // 会根据文件名打包出 home.js、a.js
            filename: '[name].js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [ 
            new HtmlWebpackPlugin({
                filename: 'home.html',
                template: './template/index.html',
                chunks: ['home']    // 打包出引用了 home.js 的html
            }),
            new HtmlWebpackPlugin({
                filename: 'a.html',
                template: './template/index.html',
                chunks: ['a']       // 打包出引用了 a.js 的html
            })
        ],
    }
    

    source-map

    代码经过babel转化和webpack打包后,错误位置指向不准确

    在production下打包,所有代码都在一行。使用source-map可以方便调试

    // webpack.config.js
    ...
        devtool: 'source-map'
    }
    
    • source-map 指向错误代码位置(行列),生成.map文件,很大(6+1k)
    • eval-source-map 同上,不单独生成文件,大(3k)
    • cheap-module-source-map 指向错误代码位置(行列),生成.map文件,小(1+1k)
    • cheap-module-eval-source-map 你猜

    watch (只打包,不会自己刷新浏览器)

        // 监控代码改变,动态打包
        watch: true,
        watchOptions: {
            poll: 1000,   // 访问1000/s
            aggregateTimeout: 500,  // 防抖 123 1231234
            ignored: /node_modules/,    // 不监控的目标
        }
    

    webpack-dev-middleware 前后端使用一个端口、解决跨域

    官方表示:development only,仅做为一种解决跨域的方法

    const webpack = require('webpack');
    const middleware = require('webpack-dev-middleware');
    const compiler = webpack({
      // webpack options
    });
    const express = require('express');
    const app = express();
     
    app.use(
      middleware(compiler, {
        // webpack-dev-middleware options
      })
    );
     
    app.listen(3000, () => console.log('Example app listening on port 3000!'));
    

    其它两种是

      devServer: { 
        proxy: {
          '/api': {
            target: 'http://n.n.n.n:nnnn', 
            ws: false,
            changeOrigin: true
          },
        },
        // 模拟数据请求
        before(app){
            app.get('/some/path', function(req, res) {
                res.json({ custom: 'response' });
            });
        }
      },
    

    按环境使用配置文件 webpack-merge

    • webpack.base.js // 基础配置
    • webpack.dev.js // 开发配置,如devServer中的source-map、代理等
    • webpack.prod.js // 生产配置,如代码压缩、shake-tree等
    var {smart} = require('webpack-merge');
    var base = require('./webpack.base.js');
    
    const OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin')
    const uglifyjsPlugin = require('uglifyjs-webpack-plugin')
    
    module.exports = smart(base, {
        mode: 'development',
        optimization: {     // 优化项
            minimizer: [
                new OptimizeCssPlugin(),
                new uglifyjsPlugin()
            ]
        },
    })
    

    多线程打包 happypack

    在项目中添加vue和moment,并用babel解析

    let Vue = require('vue')
    let moment = require('moment')
    moment.locale('zh-cn')
    
    new Vue.default({
        // el: '#app',
        data: {
            message: moment().format('lll')
        },
        render (h) {
          return h('div', this.message)
        }
    }).$mount('#app') 
    
        module: {
            rules: [
                { test: /\.js$/, use: {
                    loader: 'babel-loader',
                    options: { 
                        presets: ['@babel/preset-env']
                    }
                } } // 为了效果明显,这里故意不加exclude include
            ]
        },
    

    打包时间为2868ms。下面加入happypack

        module: {
            rules: [
                { test: /\.js$/, use: 'HappyPack/loader?id=js' }
            ]
        },
        plugins: [
            new HappyPack({
                id: 'js',
                loaders: [{
                    loader: 'babel-loader',
                    options: { 
                        presets: ['@babel/preset-env']
                    }
                }]
            })
    

    打包时间为2192ms,嗯...差别不大,分配线程也需要时间,小项目用了搞不好比不用还久

    提取公共代码 optimization.splitChunks

    写两个一样的文件

    let Vue = require('./src/vue')
    let moment = require('moment')
    moment.locale('zh-cn')
    
    new Vue({
        data: {
            message: moment().format('lll')
        },
        render (h) {
          return h('div', this.message)
        }
    }).$mount('#app') 
    
    // webpack.config.js
        entry: {
            index: './index.js',
            a: './src/a.js'
        },
        output: {
            filename: '[name].js',
            path: path.resolve(__dirname, 'dist')
        }, 
        plugins: [
            new HtmlWebpackPlugin({
                template: './template.html',
                filename: 'index.html'
            })
        ]
    

    打包出两个1M的js,下面开始分包

        optimization: {
            // 提取公共代码 分包
            splitChunks: {
                cacheGroups: {  // 缓存组
                    common: {
                        chunks: 'initial',
                        minSize: 0,
                        minChunks: 2    // 引用>=2时分包
                    }
                }
            }
        }
    

    chunks的含义是拆分模块的范围

    • async表示只从异步加载得模块(动态加载import())里面进行拆分
    • initial表示只从入口模块进行拆分
    • all表示以上两者都包括

    打包后多出了 commonaindex.js 文件 997K,原本两个1M的js现在只有6.79k。除了common再抽离一个

                    common: {
                        chunks: 'initial',
                        minSize: 0,
                        minChunks: 2    // 引用>=2时分包
                    }
                    vendor: {
                        priority: 1,    // 权重,不加会都到common里
                        test: /node_modules/,
                        chunks: 'initial',
                        minSize: 0,
                        minChunks: 1
                    }
    

    commonaindex.js 363K,vendoraindex.js 634K

    热更新

        devServer: {
            hot: true,
            port: 7070,
            contentBase: './dist'
        }, 
        plugins: [
            // 热更新
            new webpack.NamedModulesPlugin(),   // 确保模块ID稳定
            new webpack.HotModuleReplacementPlugin(),
    
    // 入口文件
    let b = require('./src/b')
    console.log(b)
    if (module.hot) {
      module.hot.accept('./src/b', () => {
        console.log('已变更')
        b = require('./src/b')
        console.log(b)
      })
    }
    
    // ./src/b.js
    module.exports = 'ggggg'
    

    npx webpack-dev-server 启动后,修改./src/b.js页面会无刷新更新

    不加两个plugin更新时会刷新页面

    相关文章

      网友评论

          本文标题:webpack - 项目优化2

          本文链接:https://www.haomeiwen.com/subject/tovjzctx.html