webpack - 项目优化2

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)