zoukankan      html  css  js  c++  java
  • webpack学习-10天搞定webpack4

     第12天课程-多页:多入口,匹配多个打包的js


    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
        mode: 'development',
        entry: {
            home: './src/home.js',
            other: './src/other.js'
        },
        output: {
            filename: '[name].js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: './src/home.html',
                filename: 'home.html',
                chunks:['home']
            }),
            new HtmlWebpackPlugin({
                template: './src/other.html',
                filename: 'other.html',
                chunks:['other']
            })
        ]
    }

    补充章节:webpack-mode


     mode分为development/production,默认为production。每个选项的默认配置如下(common指两个配置项都存在的属性):

     common:

    //parent chunk中解决了的chunk会被删除
    optimization.removeAvailableModules:true
    //删除空的chunks
    optimization.removeEmptyChunks:true
    //合并重复的chunk
    optimization.mergeDuplicateChunks:true

    production 

    //性能相关配置
    performance:{hints:"error"....}
    //某些chunk的子chunk已一种方式被确定和标记,这些子chunks在加载更大的块时不必加载
    optimization.flagIncludedChunks:true
    //给经常使用的ids更短的值
    optimization.occurrenceOrder:true
    //确定每个模块下被使用的导出
    optimization.usedExports:true
    //识别package.json or rules sideEffects 标志
    optimization.sideEffects:true
    //尝试查找模块图中可以安全连接到单个模块中的段。- -
    optimization.concatenateModules:true
    //使用uglify-js压缩代码
    optimization.minimize:true

    development

    //调试
    devtool:eval
    //缓存模块, 避免在未更改时重建它们。
    cache:true
    //缓存已解决的依赖项, 避免重新解析它们。
    module.unsafeCache:true
    //在 bundle 中引入「所包含模块信息」的相关注释
    output.pathinfo:true
    //在可能的情况下确定每个模块的导出,被用于其他优化或代码生成。
    optimization.providedExports:true
    //找到chunk中共享的模块,取出来生成单独的chunk
    optimization.splitChunks:true
    //为 webpack 运行时代码创建单独的chunk
    optimization.runtimeChunk:true
    //编译错误时不写入到输出
    optimization.noEmitOnErrors:true
    //给模块有意义的名称代替ids
    optimization.namedModules:true
    //给模chunk有意义的名称代替ids
    optimization.namedChunks:true

    webpack运行时还会根据mode设置一个全局变量process.env.NODE_ENV,

    这里的process.env.NODE_ENV不是node中的环境变量,而是webpack.DefinePlugin中定义的全局变量,允许你根据不同的环境执行不同的代码.

    生产环境下,uglify打包代码时会自动删除不可达代码,也就是说生产环境压缩后最终的代码为:

    第13天课程-配置source-map


    安装依赖

    npm install -D babel-loader @babel/core @babel/preset-env 
    
    npm install webpack-dev-server --save-dev

    devtool设置项理解,eval 可以理解为发射,不是编译阶段产生
      //devtool: 'source-map',//产生文件,可以显示行和列
      //devtool: 'eval-source-map',//不实际产生文件,但是可以显示行和列
      //devtool: 'cheap-module-source-map',//不显示列,产生文件
      devtool: 'cheap-module-eval-source-map',//不显示列,不产生文件

    试验代码src/home.js:

    class Demo{
        constructor(){
            console.loga();
        }
    }
    let d=new Demo();
    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      mode: 'production',
      entry: {
        home: './src/home.js',
      },
      output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist')
      }, 
      //devtool: 'source-map',//产生文件,可以显示行和列
      //devtool: 'eval-source-map',//不实际产生文件,但是可以显示行和列
      //devtool: 'cheap-module-source-map',//不显示列,产生文件
      devtool: 'cheap-module-eval-source-map',//不显示列,不产生文件
      module: {
        rules: [
          {
            test: /.m?js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env']
              }
            }
          }
        ]
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: './src/home.html',
          filename: 'index.html',
          chunks: ['home']
        })
      ]
    }

    14章节:watch用法,执行npm run build时候开始


    更改完代码之后,立即build,产生编译文件,

    "start": "webpack-dev-server",不会产生文件,所以用watch
    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      mode: 'production',
      entry: {
        home: './src/home.js',
      },
      output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist')
      }, 
      watch:true,
      watchOptions:{
        poll:1000,//每秒检查一次变动
        aggregateTimeout:500,//防抖延迟,500秒之后输入,
        ignored: /node_modules/ //ignored: "files/**/*.js"
      },
      module: {
        rules: [
          {
            test: /.m?js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env']
              }
            }
          }
        ]
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: './src/home.html',
          filename: 'index.html',
          chunks: ['home']
        })
      ]
    }

    15:webpack小插件介绍


    cleanWebpackPlugin:npm install clean-webpack-plugin -D

    关键代码:

    const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入清除文件插件
    new CleanWebpackPlugin()

    官方说明:详细说明

            /**
             * All files inside webpack's output.path directory will be removed once, but the
             * directory itself will not be. If using webpack 4+'s default configuration,
             * everything under <PROJECT_DIR>/dist/ will be removed.
             * Use cleanOnceBeforeBuildPatterns to override this behavior.
             *
             * During rebuilds, all webpack assets that are not used anymore
             * will be removed automatically.
             *
             * See `Options and Defaults` for information
             */
    所有output.path目录都会被一次删除,目录本身不会删除

    copyWebPackPlugin:

    const CopyWebpackPlugin = require('copy-webpack-plugin'); // 文件拷贝
    new CopyWebpackPlugin([{from:'./doc',to:'./'}])

    bannerPlugin:

    let webpack=require('webpack');
    new webpack.BannerPlugin('版权所有,违反必究 2019 copyright')

     本章节webpack配置文件

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入清除文件插件
    const CopyWebpackPlugin  = require('copy-webpack-plugin'); // 引入清除文件插件
    let webpack=require('webpack');
    
    module.exports = {
      mode: 'development',
      entry: {
        home: './src/home.js',
      },
      output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist')
      }, 
      module: {
        rules: [
          {
            test: /.m?js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env']
              }
            }
          }
        ]
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: './src/home.html',
          filename: 'index.html',
          chunks: ['home']
        }),
        new CleanWebpackPlugin(),
        new CopyWebpackPlugin([{from:'./doc',to:'./'}]),
        new webpack.BannerPlugin('版权所有,违反必究 2019 copyright')
      ]
    }

     16章节:webpack跨域问题


    webpack端口默认是8080 如果请求这么写,会跨域,跨域是浏览器本身的限制,如果使用浏览器跨域设置,可以请求到数据

    1:devServer-proxy设置

    本地express服务器:localhost:3000/api/user
    
    代理设置:proxy:{'/api':'http://localhost:3000'}
    
    但是不是服务端每个接口都是api开头的,所以需要用下面的方式 本地express服务器:localhost:
    3000/user 代理devServer设置
      proxy:{
        '/api':{
         target:'http://localhost:3000',
         pathRewrite:{'/api':''}
        }
      }
     

    2:单纯模拟数据mock 启动钩子函数

    3:有服务端,但是不想用代理处理,用express 启动webpack 端口用express端口

    npm install webpack-dev-middleware --save-dev   //安装依赖
    server.js
    
    let express = require('express');
    let config=require('./webpack.config');
    const webpack = require('webpack');
    const middleware = require('webpack-dev-middleware');
    const compiler = webpack(config);
    let app = express();
    app.use(
      middleware(compiler, {
      })
    );
    app.get('/api/user', (req, res) => {
        res.json({ "name": "珠峰设计-express" });
    })
    app.listen(3000);

    webpack.config.js

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入清除文件插件
    const CopyWebpackPlugin = require('copy-webpack-plugin'); // 引入清除文件插件
    let webpack = require('webpack');
    
    module.exports = {
      mode: 'development',
      entry: {
        home: './src/home.js',
      },
      devServer: {
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        before(app) {
          console.log(app);
          app.get('/before', (req, res) => {
            res.json({ "name": "我试mock数据-before" });
          })
        },
        port: 9000,
        /*proxy:{
          '/api':'http://localhost:3000'
        } */
        proxy: {
          '/api': {
            target: 'http://localhost:3000',
            pathRewrite: { '/api': '' }//需要先启动3000端口的服务
          }
        }
      },
    
      output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist')
      },
      module: {
        rules: [
          {
            test: /.m?js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env']
              }
            }
          }
        ]
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: './src/home.html',
          filename: 'index.html',
          chunks: ['home']
        }),
        new CleanWebpackPlugin(),
        new CopyWebpackPlugin([{ from: './doc', to: './' }]),
        new webpack.BannerPlugin('版权所有,违反必究 2019 copyright')
      ]
    }

    17:resolve属性的配置,解析的意思,文件查找别名后缀等配置


    Webpack 在启动后会从配置的入口模块出发找出所有依赖的模块,Resolve 配置 Webpack 如何寻找模块所对应的文件。 Webpack 内置 JavaScript 模块化语法解析功能,默认会采用模块化标准里约定好的规则去寻找,但你也可以根据自己的需要修改默认的规则

    安装后模块:就是会在node_modules里面Bin里面有,不需要"/"

    模块目录指定:

    别名:引入bootstrap样式为例

    alias:名称比较长,但是文件名称比较长,想取一个短的名字

    mainFields 但是能不能先找style 再找js mainFields:['style','main'] 字段名称为bootstrap里面package.json key

    extensions: 后缀扩展

       默认:extensions: ['.js', '.json']当访问aa 先找aa.js 再找aa.json如果找不到,报错

      如果需要typescript需要改成extensions: ['.ts', '.js', '.json']

      需要css的话,把css加进去

    mainFiles:文件名,暂时没有使用场景

     18:定义环境变量


     把环境变量注入代码里面,插件:new webpack.

        new webpack.DefinePlugin({
         'DEV':"'dev'",
         'DevTest':JSON.stringify('devTest'),
         'DevBoolean':true,
         'DevBooleanWithSingle':'true',
         'EXPRESSIONWITHNOTDOT':'1+1',
         'EXPRESSIONWITHDOT':JSON.stringify('1+1'),
        }),

    输出结果:

    19;区分不同环境变量


    webpack.config.js分开生产和开发环境,

    webpack.base.js :公共的

    webpack.dev.js 开发的

    webpack.prod.js 生产的

    安装插件npm install webpack-merge -D

    webpack.dev.js文件内容 ,这样我们就可以把配置给分开

    const { smart } = require('webpack-merge');
    const base = require('./webpack.base.js');
    module.exports = smart(base, {'mode':'development'})

     20:优化设置


     新建一个空的工程并安装插件

    npm init -y
    npm install webpack webpack-cli html-web
    pack-plugin @babel/core babel-loader @babel/preset-env @babel/preset-react jquery -D

    >webpack配置里面的noParse:不解析依赖项

    src-index.js文件
    import jquery
    from 'jquery';

    这样反复编译几次发现,编译时间是缩短了,我电脑表现大概节约200ms时间

     >IgnorePlugin插件:忽略某些模块,不打包进来

    webpack配置里面exclude include排除目录(node_modules),包含src 

     安装moment 时间处理库:npm insall moment -D

     安装开发服务器:npm install webpack-dev-server

    webpack.config.js文件

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const webpack=require('webpack');
    
    module.exports = {
        entry: './src/index.js',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist'),
        },
        module: {
            rules: [
                {
                    test: /.m?js$/,
                    exclude: /(node_modules|bower_components)/,
                    include:path.resolve("src"),
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env', '@babel/preset-react']
                        }
                    }
                }
            ]
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: './public/index.html',
            }),
            new webpack.IgnorePlugin(/./locale/,/moment/)
    
        ],
    };

    index.js

    import jquery from 'jquery';
    import moment from 'moment';
    import 'moment/locale/zh-cn';
    moment.locale('zh-cn');//这一句不引入也正确
    let r=moment().endOf('day').fromNow();
    console.log(r);

     >dllPlugin插件:减少打包体积

    安装npm install react react-dom

    >happypack多线程打包js,css打包 中间插入一层happypack

    >webpack自带的一些优化,避免不必要的tree-shaking,作用域提升scope hosting

    生产环境去除没有用的代码,开发环境有的,tree-shaking

    只有import 管用,require不可以,es6模块会把结果放到default对象上

    前端推荐import 

    webpack会省略一些可以简化的代码

    25:webpack抽取公共代码 optimization-splitChunks-cacheGroups里面配置,多入口文件


    webpack配置文件
    
    optimization:{
    splitChunks:{
    cacheGroups:{
    common:{
    chunks:'initial',//抽离阶段
    minSize:0,抽离大小
    minChunks:2//引用多少次就开始抽离
    
    },
    vendor:{
    priority:1, //避免直接走第一步,不走第二步
    test:/node_modules/,
    chunks:'initial',
    minSize:0,
    minChunks;2
    
    }
    
    
    
    
    
    }
    }
    }

    26:懒加载功能webpack


    意义:安装插件@babel/plugin-syntax-dynamic-import 

    vue react的路由懒加载实现

    button的点击事件里面代码

    import('./source.js');

    options:{
        presets:['@babel/preset-env','@babel/preset-react'],
        plugins:['@babel/plugin-syntax-dynamic-import ']
    }

    27:webpack热更新 开发环境用 默认强制更新,重新编译


    devserver:hot:true

    两个插件:webpack.NamedModulesPlugin  /webpack.HotModuleReplacementPlugin

    index.js

    import s from './a.js';
    if (module.hot) {
        module.hot.accept('./a.js', (s) => {
            let a=import('./a');//
            a.then(function(response){
                console.log(response);
            });
            let b=require('./a.js');
            console.log(b);
    
        })
    
    }
    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const webpack=require('webpack');
    
    module.exports = {
        entry: './src/index.js',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist'),
        },
        devServer:{
         port:3000,
         open:true,
         hot:true,
         contentBase:'./dist'
        },
        module: {
            rules: [
                {
                    test: /.m?js$/,
                    exclude: /(node_modules|bower_components)/,
                    include:path.resolve("src"),
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env', '@babel/preset-react']
                        }
                    }
                }
            ]
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: './public/index.html',
            }),
            new webpack.IgnorePlugin(/./locale/,/moment/),
            new webpack.NamedModulesPlugin(),
            new webpack.HotModuleReplacementPlugin()
    
        ],
    };

    28-33:webpack-tapable 同步钩子和异步钩子 


    webpack 本质事件流,主要依赖于发布订阅模式

  • 相关阅读:
    CodeForces 682B Alyona and Mex (排序+离散化)
    CodeForces 682A Alyona and Numbers (水题)
    CodeForces 682E Alyona and Triangles (计算几何)
    CodeForces 176B Word Cut (计数DP)
    CodeForces 173C Spiral Maximum (想法、模拟)
    Spring源码剖析3:Spring IOC容器的加载过程
    Spring源码剖析2:初探Spring IOC核心流程
    深入理解JVM虚拟机13:再谈四种引用及GC实践
    深入理解JVM虚拟机12:JVM性能管理神器VisualVM介绍与实战
    深入理解JVM虚拟机11:Java内存异常原理与实践
  • 原文地址:https://www.cnblogs.com/liuguiqian/p/11287631.html
Copyright © 2011-2022 走看看