个人对webpack的学习笔记

·  阅读 138

/**

  • HMR hot module replacement 热模块替换 / 模块热替换
  • 作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)
  • 极大的提升了构建速度
  • 样式文件可以使用HRM 因为style-loader内部实现了
  • js:默认不使用HMR功能--->修改js代码,添加支持HMR功能的代码
  • 注意:HMR功能对js的处理--->只能处理非入口js文件的其他文件。
  • html:默认不能使用HRM功能,同时会导致问题:HTML文件不能热更新了~(
  • 不需要做热更新功能,因为只有一个html文件)
  • 解决: 修改entry入口,将html文件引入
  • 注意:生产环境不能使用HMR,使用缓存 / /*
  • 缓存
  • babel缓存
  • cacheDirectory:true
  • 文件资源缓存
  • hash:每次webpack会产生唯一一个hash值
  • 问题:因为js和css使用同一个hash值。
  • 如果重新打包,会导致所有缓存失效(可能我只改变一个文件)
  • chunkhash:根据chunk生成的hash值,如果打包来源于同一个chunk,那么hash值就一样
  • 问题:js和css的值还是一样的,因为css是在js中被引入的,所以同属于一个chunk
  • contenthash:根据文件的内容生成hash,不同文件hash值不一样;

*/

/**

  • tree shaking:去除无用代码

  • 前提:1.必须使用ES6模块化 2.开启production环境

  • 作用:减少代码体积

  • 在package.json中配置

  • 'sideEffects':false 所有代码都没有副作用(都可以进行 tree shaking )

  • 问题:可能会把css/@babel/polyfill(副作用)文件干掉

  • "sideEffects":["*.css"]//排除所有的css文件 */ const HtmlWebpackPlugin = require('html-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const PostcssPresetEnv = require('postcss-preset-env') const TerserWebpackPlugin=require('terser-webpack-plugin') const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin') const WorkboxWebpackPlugin=require('workbox-webpack-plugin') const AddAssetHtmlWebpackPlugin=require('add-asset-html-webpack-plugin') const { resolve } = require('path') const webpack = require('webpack') process.env.NODE_ENV = 'development' module.exports = { //单入口文件 entry: './src/index.js', //代码分割 //多入口文件打包,将多入口文件分割成多个模块 //问题:不能将公共代码分割,导致公共代码重复加载,增大代码体积 // entry:{ // index:"./src/print.js", // test:"./src/index.js" // }, // entry: ['./src/index.js','./src/index.html']//开启html文件的热更行 output: { path: resolve(__dirname, 'build'), // filename: 'bundle.js' filename: 'bundle.[hash:9].js' // filename: '[name].js'

    //所有资源引入公共路径前缀---> img/a.jpg -->/img/a.jpg
    // ,publicPath:'/'
    
    ,chunkFileName:'[name]._chunk.js'//非入口chunk的名字(import动态引入)
    复制代码

    }, module: { rules: [ /** * 正常来讲,一个文件只能被一个loader处理, * 当一个文件被多个loader处理,那么一定要指定loader的执行顺序, * 先执行eslint在执行babel // */ { // test: /.js$/,

                    /**
                     * eslint是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具,
                     * 它的目标是保证代码的一致性和避免错误。(官方翻译)
                     * exclude排除node_moudles的检查,eslint语法检查需要
                     * eslint eslint-loader eslint-config-airbnb-base 
                     * eslint-plugin-import四个搭配使用,还需要在package.json中
                     * 配置eslintConfig--->"eslintConfig":{
                                   "extends":"airbnb-bas" },
                                   airbnb为编码规范(学习)github下载
                                   fix:true为自动修改代码,使代码规范
                                   enforce:'pre'指定哪个loader先执行
                     */
                    exclude: /node_moudles/,
                    enforce: "pre",
                    loader: 'eslint-loader',
                    options: {
                        fix: true
                    }
                },
        {
            /**
             * oneOf的意思是以下loader只会匹一个
             * 不能有两个loader处理同一类型的文件,
             * 如果有多个loader要处理同一类型的文件,需要提取
             * 出其他loader放到oneOf外面,直留一个loader在里面
             * oneOf能够提升代码的构建速度
             */
            oneOf:[
                {
                    test: /\.css$/,
                    use: [
                        MiniCssExtractPlugin.loader,
                        /**
                         * css-loader---->css-loader是从入口文件中将css文件转换成javascript
                         *能够识别的文件,style-loader===>syle-loader是在html文件中创建style标签
    
                         */
                        'css-loader',
                        {
                            loader: 'postcss-loader',
                            options: {
                                ident: 'postcss',
                                plugins: () => [
                                    /*
                                postcss-preset-env---->是处理css3对浏览器兼容性的问题、
                                可以对css3的某些属性增加前缀,处理兼容问题,
                                还需要配置browserslist:{
                                    "development":[
                                        "last 2 chrome version",
                                        "last 2 firefox version",
                                        "last 2 safari version",
                                    
                                    ],
                                    production:[
                                        ">0.1%",
                                        "not dead",
                                        "not op_mini all"
                                    ]
                                }
                              指定browserslist在哪种环境下起作用,需要设置process.env.NODE_ENV的值
                              "development"在开发环境下起作用,"production"在生产环境下起作用
                                */
                                    require('postcss-preset-env')()
                                ]
                            }
                        }
                    ]
                },
                {
                    test: /\.(jpg|png|gif)/,
                    //url-loader--->url-loader是基于file-loader设计的,增加了limit
                    //属性,对图片大小进行判断,然后选择对其进行编码操作
                    //esModule:false是关闭escript语法,因为html-loader采用的是commonjs
                    //进行解析的,必须同步
                    //outputPath配置是将文件输出的路径
                    //hash:8文件名字使用8位的hash值命名,ext是源文件的扩展名
                    loader: 'url-loader',
                    options: {
                        limit: 8 * 1024,
                        esModule: false,
                        name: '[hash:8].[ext]'
    
                    }
                },
                /**
                 * html-loader--->html-loader是为了解析html里面加载的图片
                 */
                {
                    test: /\.html$/,
                    loader: "html-loader"
    
                },
                {
                    test: /\.(eot|svg|ttf|woff|woff2)/,
                    loader: 'file-loader'
                },
                
                /**
                 * JS兼容处理安装babel-loader @babel/core @babel/preset-env
                 * babel-loader--->babel-loader是npm的一个包,它使得webpack可以
                 * 通过babel转义javascript语句,
                 * @babel/core---->@babel/core这是babel的核心库,负责解析。
                 * @babel/preset-env--->@babel/preset-env负责各种插件的打包组合,
                 * 各种转义规则的统一设定,目的是告诉loader要以什么规则转来转化成对应的js版本
                 * 1、基本js的兼容处理--->@babel/preset-env只能转化基本语法,高级语法不能不能转换
                 * 2、全部js的兼容处理--->将全部兼容代码引入,会增大体积(不考虑使用)
                 * 3、按需加载js的兼容处理--->core-js只加载需要处理的js兼容代码(配合@babel/preset-env使用)
                 */
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    use:[
                        {
    
                            /**
                             * 多进程打包
                             * 进程启动大概600ms,进程通信也有开销
                             * 只有工作时间消耗比较长,才需要多进程打包(比如有大量的js文件)
                             */
                            loader:'thread-loader',
                            options:{
                                workers:2
                            }
                        },
                        {
                            loader: 'babel-loader',
                            //只使用@babel/preset-env处理兼容的代码
                            // options:{
                            //     presets:['@babel/preset-env']
                            // }
                            //使用@babel/preset-env和core-js处理js兼容
                            options: {
                                //预设指示babel做怎样的兼容处理
                                presets: [
                                    ['@babel/preset-env',
                                        {
                                            //按需加载
                                            useBuiltIns: 'usage',
                                            //指定core-js版本
                                            corejs: {
                                                version: 3
                                            },
                                            //指定兼容性做到哪个版本浏览器
                                            targets: {
                                                chrome: '60',
                                                firefox: '60',
                                                ie: '9',
                                                safari: '10',
                                                edge: '17'
                                            }
                                        }
                                    ]
                                ],
                                //开启babel缓存,
                                //会读取之前的缓存
                                //此方法会强制缓存文件,是的文件在缓存期间内无法被改变
                                //解决方法,每次要更新就给要更新的文件改变名字
                                cacheDirectory:true
                            }
                        }]
                  
                }
            ]
        }
    ]
    复制代码

    }, plugins: [ new webpack.DllReferencePlugin({ //告诉webpack哪些库不参与打包,同时使用是的名称也得变 manifest:resolve(__dirname,'dill/manifest.json') }), // //在HTML加载指定的资源 // new AddAssetHtmlWebpackPlugin({ // filepath:resolve(__dirname,'dill/jquery.js') // }) // ,

    //生成HTML文件
    new HtmlWebpackPlugin({
        template: "./src/index.html",
        filename: "index.html",
        //压缩html代码
        //压缩js代码只需要将mode改为production
        minify: {
            //清除空格
            collapseWhitespace: true,
            //清除评论
            removeComments: true
        }
    }),
    
    //将css从js文件抽取出来,//自带了一个loader分析处理css文件
    new MiniCssExtractPlugin({
        filename: "bundle.[hash:9].css"
    }),
    //压缩抽取出来的css文件
    new OptimizeCssAssetsWebpackPlugin(),
    // new webpack.HotModuleReplacementPlugin()
    new WorkboxWebpackPlugin.GenerateSW({
        /**
         * 1、帮助serviceworker快速启动
         * 2、删除旧的serviceworker
         * 生成一个serviceworker配置文件
         */
        clientsClaim:true,
        skipWaiting:true
    })
    复制代码

    ], /**

    • 代码分割

    • 1.可以将node_modules中代码单独打包一个chunk最终输出

    • 2.自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独的一个文件 / optimization:{ splitChunks:{ chunks:'all', minSie:301024 ,//分割的chunk最小为30kb maxSize:0,//最大没有限制 minChunks:1,//要提取的chunk至少被引用一次 maxAsyncRequests:5 ,//按需加载时并行加载的文件的最大数目 maxInitialRequests:3,//入口js文件最大并行请求数量 automaticNameDelimiter:'~',//名称连接符 name:true,//可以使用命名规则 cacheGroups:{//分割chunk的组 //node_modules文件会被打包到vender组的chunk中--->vender~xxx.js //满足上面的公共规则 vendors:{ test:/[\/]node_modules[\/]/, //优先级 priority:-10,

           },
           default:{
               //要提取的chunk至少被引用两次,
               minChunks:2,
               //优先级
               priority:-20,
               //如果当前要打包的模块,和之前已经被提取的模块是同一个模块,
               //就会复用,而不是重新打包
               reuseExistingChunk:true
           }
       }
      复制代码

      }, //将当前模块的记录的其他模块的hash单独打包为一个文件runtime runtimeChunk:{ name:entrypoint => runtime-${entrypoint.name} }, minimizer:[ //配置生产环境的压缩方案:js和css

       new TerserWebpackPlugin({
           //开启缓存
           cache:true,
           //开启多进程打包
           parallel:true,
           //开启source-map
           sourceMap:true
      
       })
      复制代码

      ] } , mode: 'production', //解析模块规则 resolve:{ //配置解析模块路径别名:优点简写路径 缺点路径没提示 alias:{ css$:resolve(__dirname,'src/css') }, //配合省略文件路径的后缀名 extensions:['.js','.json','jsx'], //告诉webpack解析模块是去哪个目录找 modules:[resolve(__dirname,'./node_modules'),'node_modules']

    }, externals:{ //当html使用cdn的方式引入第三方的库时, //可以使用externals拒绝被引入的库进行打包,加快打包速度 jquery:'jQuery' }, devServer: {

    watchContentBase:true,
    watchOptions:{
        //忽略文件,不监视node_modules中的文件
        ignored:/node_modules/
    },
    //运行代码的目录
    contentBase: resolve(__dirname, 'build'),
    port: 3000,
    open: true,
    compress: true,
    // hot:true//开启热更新功能
    //不要显示启动服务器的日志信息
    clientLogLevel:'none',
    //除了一些基本启动信息以外,其他内容都不要显示
    quiet:true,
    //如果出错了,不要全屏提示
    overlay:false,
    proxy:{
        //一旦devserver服务器接受到/api/xxx的请求,就会把请求发送到另外一个服务器上
        '/api':{
            target:'http://localhost:3000',
            //发送请求时,路径重写:将/api/xxx--->/xxx(去掉/api)
            pathRewrite:{
                '^/api':''
            }
        }
    }
    复制代码

    }, // devtool:'inline-source-map' }

/**

  • source-map:一种提供源代码到构建后代码的映射技术(如果构建后代码错了,通过映射
  • 可以追踪到源代码错误的信息和错误位置)
  • [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
  • source-map:外部创建.map文件
  • 错误代码准确信息,和源代码错误位置
  • inine-source-map:内联,外部不生成.map文件
  • 只生成一个内部的source-map
  • 错误代码准确信息,和源代码的错误位置
  • hidden-source-map:外部
  • 错误代码原因,带没有错误代码的位置
  • 不能追踪源代码错误,只能提示到构建后的代码的错误位置
  • eval-source-map:内联
  • 每一个文件都生成对应的source-map,都在eval
  • 错误代码准确信息,和源代码的错误位置
  • nosources-source-map:外部创建
  • 错误代码准确信息,但没有任何源代码的信息
  • cheap-source-map:外部
  • 错误代码准确信息,和源代码的错误位置
  • 只能精确到行
  • cheap-module-source-map:外部创建
  • 错误代码准确信息,和源代码的错误位置
  • module会将loader中的source-map加入
  • 内联和外部的区别:
  • 1、外部生成了.map文件,内联没有
  • 2、内联构建速度更快
  • 开发环境:要求速度快,调试友好
  • 速度快:(eval>inline>cheap>...)
  • eval-cheap-source-map
  • eval-source-map
  • 调试更友好:
  • source-map
  • cheap-module-source-map
  • cheap-source-map
  • -->eval-source-map(开发环境优选) / eval-cheap-module-source-map
  • 生产环境:源代码要不要隐藏,调试要不要更友好
  • 内联会让代码体积更大,所以生产环境不用内联
  • nosources-source-map 代码全部隐藏
  • hidden-source-map 只会隐藏源代码,会提示构建后代码错误信息
  • -->source-map(调试更友好,生产环境优选) / cheap-module-source-map(速度快)

*/

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改