最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • webpack4.0笔记

    正文概述 掘金(番茄一个)   2021-02-26   578

    Ⅰ. 开发环境配置

    1. 安装依赖
    // js的构建工具都是基于nodejs的 , 安装的依赖都是生产模式
    
    npm i webpack webpack-cli --save-dev
    
    2. module的use数组里面loader执行顺序

    ​ 下 ==> 上 ( 右 ==> 左 )

    3. 处理 css文件
    css-loader : 将css文件变成commonjs模块加载到js中, 里面内容是样式字符串
    style-loader : 创建style标签 , 将js中的样式资源插入进行, 添加到head标签中
    
    4. 处理scss/less文件
    // webpack里面用sass/less要安装相应依赖 
    npm install --save-dev node-sass sass-loader
    
    npm install --save-dev less less-loader
    
     {
            test: /\.less$/,
            use: [{ loader: "style-loader" },{ loader: "css-loader" }, { loader: "less-loader" }],
     },
    
    5. 处理html资源
    html-webpack-plugin插件 (注意 : 不是html-loader)
    
    作用 : 默认会创建一个空的html文件 , 自动引入打包输出的所有资源 (js/css文件等)
    
    // 安装 npm i html-webpack-plugin -D
    
    const HtmlWebpackPlugin = require("html-webpack-plugin")
    
     plugins: [
          // 创建一个实例
         new HtmlWebpackPlugin({
             // 模版 : 将路径中的html文件作为模版复制 , 并添加引入打包输出的所有资源 css/js
             template: "./src/index.html",
             minify: {
                 removeComments: true, //清理注释
                 collapseWhitespace: true, //清理空格
             },
         })
      ],
    
    6. 打包图片资源
    // 默认使用url-loader , 但仅仅能处理样式中引入的图片资源
    url-loader , file-loader (url-loader依赖于file-loader) 
    
    // 处理html中的img引入图片 (负责img引入, 从而能被url-loader处理)
    html-loader 
    

    注意 : url-loader默认使用es6模块化解析, 而html-loader引入图片是commonjs规范 , 解析时候会报错

    解决 : 关闭url-loader的es6模块化 , 使用commonjs解析 esModule : false

    // loader相关配置
    	{
            test: /\.(jpg|png|gif)$/,
            use: [
              {
                loader: "url-loader", //url-loader依赖于file-loader
                options: {
                  limit: 8 * 1024,
                    /*    图片小于8kb就是用base64的方式
                          优点: 减少请求数量(减轻服务器压力) 缺点: 图片体积会更大(文件请求速度变慢)
                          所以一般不对大图片进行base64处理 , 对8-12kb以下的小图片进行base64处理 
                          比如 : 有个9kb的图片 , 就可以设置 10*1024
              		*/
                 esModule: false,
                 name: "[hash:8].[ext]" // 重命名 取到hash值前8位  .[ext] 保留原来的后缀名
                }
              }
            ]
        },
        {
            test: /\.html$/,
            use: [
              {
             	// 处理html中的img标签图片 (负责img引入, 从而能被url-loader处理)
                loader: "html-loader"
              }
            ]
        }
    
    // 如果打包后的的html出现 // module 开头的乱码 , 可能是配置了两次 html-loader
    
    
    // plugin相关配置
    
     const HtmlWebpackPlugin = require("html-webpack-plugin");
    
     plugins: [
        // 创建一个实例
        new HtmlWebpackPlugin({
          // 模版 : 将路径中的html文件作为模版复制 , 并添加引入打包输出的所有资源 css/js
          template: "./src/index.html",
          // minify: {
          //   removeComments: true, // 清理注释
          //   collapseWhitespace: true // 清理空格
          // }
        })
      ],
    
    
    7. 打包其他资源
          {
            /* 打包其他资源(排除资源,原样输出) */
            exclude: /\.(css|js|html)$/,
            use:[
                    {
                        loader: "file-loader",
                        options: {
                          name: "[hash:8].[ext]"
                        }
                    }
            	]  
          }
    
    
    
    8. 开发服务器devServer
    webpack-cli4的启动命令 webpack serve 
    webpack-cli3的启动命令 npx webpack-dev-server
    
    
    // 作用 : 自动编译 , 自动打开浏览器 , 自动刷新
    // 特点 : 只会在内存中编译打包 , 不会有任何输出
    
    // npm i webpack-dev-server -D  , 卸载安装webpack-cli指定版本,避免兼容性踩坑
    // npm uninstall webpack-cli -D
    // npm install  webpack-cli@3.3 -D
    
     devServer: {
        contentBase: path.resolve(__dirname, "build"),  // 打包输出的文件夹
        open: true,     // 自动打开浏览器
        port: 3003,     // 端口
        compress: true,  // gzip压缩代码体积
     	inline:true       // 实时刷新 
     }
    
    

    天坑 : 默认启动指令: npx webpack-dev-server 可以在package.json中修改 , 默认指令可能在启动后不能自动刷新 , 还是修改比较好 ( 傻b配置坑过我一晚上)

    // 在package.json中配置 
    
     "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "dev": "webpack-dev-server --mode development"
      }
    // 之后 用npm run dev就能启动devServer
    
    
    8.1 报错: Cannot find module ‘webpack-cli/bin/config-yargs‘
    // webpack最新版和webpack-cli4冲突 
    // 卸载全局和本地的最新webpack-cli , 安装指定版本
    npm uninstall webpack-cli -g
    npm uninstall webpack-cli -D
    
    npm install  webpack-cli@3.3 -D
    npm install  webpack-cl3.3 -g
    
    
    8.2 devServer 不能自动刷新
    // 绝壁是在output里配置了publicPath:'./'
    // 要么不写 , 要么写成下面
    
    publicPath:"/dist/"    // 虚拟路径 , devServer运行时 webpack的虚拟路径
    
    // 这里写的是什么 , 打包后的html文件引入的main.js路径前面就是什么
    <script src="/dist/js/main.js"></script></body>
    
    
    9. 各种打包报错
    报错 1 : Cannot find module 'webpack-cli/bin/config-yargs'
    webpack-cli版本冲突了 
    
    先把webpack-cli卸载,再安装执行npm install webpack-cli@3 -D
    
    
    报错 2 : 打包后控制台报错Refused to apply style from 'http://localhost:7099/iconfont/iconfont.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
    // 在devServer的配置中加入 publicPath:'./'
      devServer: {
        contentBase: path.join(__dirname, "build"), // 项目构建打包输出的路径
        compress: true, // 启动gzip压缩 , 代码体积更小
        open: true, // 自动打开浏览器
        port: 7099,
        publicPath:'./'
      }
    
    
    报错 3 : document is not defined
     webpack://guigu_webpack/./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js?:93  
        var style = document.createElement('style');
    
    
    解决方案: src中的index.html文件引入了css样式 , 或者main.js入口文件 , 删掉即可
    
    

    webpack4.0笔记

    报错 4. Automatic publicPath is not supported in this browser
    // 输出配置output里面加上
    	
    publicPath:'./'
    
    
    报错5. 打包后背景图片不显示
    // 使用 mini-css-extract-plugin插件单独提取css后背景图不显示, 在options里加 publicPath: '../'
    { 
        loader: MiniCssExtractPlugin.loader,
         options:{
              publicPath: '../'
         	}
    }
    // 加在处理css/scss/less的配置中 , 不是加在处理img的配置中 , 我是傻逼
    
    
    报错6. export default webpack_public_path + "others/e86c5939.less";
    打包其他文件时 , 没有把对应文件的格式排除
    
    
    10. 配置文件打包输出的路径
    //  loader配置outputPath输出到文件夹 
    
    1. css/less/scss的输出路径不需要配置文件夹路径 , 因为能打包进 build.js文件 ,不然报错
    2. html-loader处理html中img标签引入的图片资源时 , 不用写outputPath , 不然报错
    
    
    10.1 傻逼报错 configuration.output has an unknown property 'outputPath'
     Webpack has been initialized using a configuration object that does not match the API schema.
     - configuration.output has an unknown property 'outputPath'. These properties are valid:
    
    
    要么是出口output中'path'写成了"outputPath
    要么是打包css/scss/less的时候 options里写了outputPath
    
    
    11. 每次打包前清理build文件夹的目录
    // 注意: 尽量别用 ,devServer的时候 , 会把build里的文件都删了 , 但是又不打包输出
    
    
    // 依赖 clean-webpack-plugin 插件
    npm i --save-dev clean-webpack-plugin
    
    // 解构 , 再plugins配置里调用
    // 注意是解构 , 不是直接引用
    const { CleanWebpackPlugin } = require("clean-webpack-plugin"); 
    
     // 每次打包前清除一遍build目录下的文件夹
     // 在最新版的webpack中 ( )中不需要写里面的目标路径,会自动清除生成的文件夹,比如是build文件夹
     new CleanWebpackPlugin()
    
    

    Ⅱ. 处理兼容和压缩

    1. css相关处理
    1.1 提取css到单独文件
    // mini-css-extract-plugin 插件
    // 将CSS提取为独立的文件的插件,对每个包含css的js文件都会创建一个CSS文件,支持按需加载css和sourceMap
    npm i mini-css-extract-plugin -D
    
    

    MiniCssExtractPlugin.loader 取代 style-loader , 提取 js中打包的各个css文件整合成单独文件 , 就不需要插入style标签中了

    // 如果less/scss/css 样式都有的话 , 就得每个loader配置里面都替换
    
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
     use: [
              // { loader: "style-loader" },
              { loader: MiniCssExtractPlugin.loader }, // 注意不要写成了字符串
              { loader: "css-loader" },
              { loader: "sass-loader" }
          ]
    
    // 在plugins中
     new MiniCssExtractPlugin({
          filename: "css/build.css" // 配置单独提取出来的css文件的路径以及名字
        })
    
    
    1.2 css兼容处理及压缩
    // 需要安装 postcss-loader  postcss-preset-env
    /*
                css兼容性处理:postcss --> postcss-loader postcss-preset-env
                        帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
    
            "browserslist": {
              // 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
              "development": [
                "last 1 chrome version",
                "last 1 firefox version",
                "last 1 safari version"
              ],
              // 生产环境:默认是看生产环境
              "production": [
                ">0.2%",
                "not dead",
                "not op_mini all"
              ]
            }
          */
    
    
    - 新建postcss.config.js 配置文件 
    
      ```js
      module.exports = {
        plugins: [
          // 使用postcss插件
          require("postcss-preset-env")
        ]
      };
    
    
    • 在package.json中写browserslist的配置

      "browserslist": {
                
                    "development": [
                      "last 1 chrome version",
                      "last 1 firefox version",
                      "last 1 safari version"
                    	],
                     
                    "production": [
                      ">0.2%",
                      "not dead",
                      "not op_mini all"
                    ]
      }
        
      
    • 默认是看生产模式的browserslist配置 , 如果要改成开发模式 , 要设置nodejs环境变量

      // 设置nodejs环境变量
      process.env.NODE_ENV = 'development';
        
      
    • 完整代码

      {
          test: /\.css$/,
              use: [
                MiniCssExtractPlugin.loader,
                'css-loader', 'postcss-loader'
              ]
      }
        
        
      
    • 压缩css及其简单

      // 安装 optimize-css-assets-webpack-plugin , 然后直接在plugins里配置调用即可
        
      npm i optimize-css-assets-webpack-plugin -D 
        
      const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
        
      // plugins里配置调用即可
        new OptimizeCssAssetsWebpackPlugin();
        
      

      项目上线前记得要压缩css代码

    1.3 less/sass的兼容处理
    /* 	
    	postcss-loader 不能处理less/sass代码
    	和css处理相同 , 只是要把postcss-loader , 放在 less-loader 和 css-loader中间 , 执行顺序		less-loader先转换成css , 再处理兼容
    */
    
    {
        test: /\.css$/,
            use: [
              MiniCssExtractPlugin.loader,
              'css-loader', 'postcss-loader','less-loader'
            ]
    }
    
    
    1.4 复用 loader 处理css/sass/less兼容
    const commonCssLoader =  [
              MiniCssExtractPlugin.loader,
              'css-loader', 'postcss-loader'
            ]
    
    // 代替前面重复代码 
    
    
    2. js语法检查 -- eslint
    // 1. 注意 eslint只检查自己写的代码 ,第三方的库是不用检查的 , 所以要排除node_modules里的模块
    
    // 2. 设置检查规则 , 在package.json中写eslintConfig 配置 , 继承airbnb-base的配置
    /*
    	"eslintConfig": {
    						"root":true,
        					"extends": "airbnb-base"
      					}
    */
    
    npm i eslint eslint-loader eslint-config-airbnb-base eslint-plugin-import -D
    // eslint-config-airbnb-base 不包含react的插件
    
    
    • 代码 :

      // 开发调式时候忽略下一行的eslint检查 , 上线时候注意删掉
      // eslint-disable-next-line
        
      // loader如下配置
            {
              test: /\.js$/,
              exclude: /node_modules/, // 一定要排除, 不检查node_modules里的模块
              loader: "eslint-loader",
              options: {
                // 自动修复eslint的错误
                fix: true
              }
            }
        
      // package.json中如下配置 
        
          "eslintConfig": {
              "root":true,
              "extends": "airbnb-base"
            }
        
      
      
      ###### 2.1 报错 : Failed to load config "airbnb-base" to extend from.
      
      ![image-20201021202722429](C:\Users\Jiraiya\AppData\Roaming\Typora\typora-user-images\image-20201021202722429.png)
      
      ```js
      // 解决方法 
      
      在上面eslintConfig的配置中忘加 "root":true
    
    

    webpack4.0笔记

    3. js兼容性处理 -- babel

    推荐第三种方法 : 按需解决兼容

    3.1 基础js兼容处理
    // 使用 babel-loader @babel/preset-env @babel/core
    npm i babel-loader @babel/preset-env @babel/core -D
    
    // js兼容性处理
          {
            test: /\.js$/,
            exclude: /node_modules/, // 一定要排除, 不检查node_modules里的模块
            use: [
              {
                loader: "babel-loader",
                options: {
                  // 预设: 指示babel做怎么样的兼容处理
                  presets: ["@babel/preset-env"]
                }
              }
            ]
          }
          ```
    
    
    3.2 全部 js兼容处理
    // 极其简单 安装 @babel/polyfill 并引入即可
    npm i @babel/polyfill -D 
    
    import '@babel/polyfill'
    
    
    3.3 按需解决兼容
     npm i core-js babel-loader @babel/core  @babel/preset-env @babel/plugin-transform-runtime  -D 
    
    // 使用此方案 , 就不能再用第二种方案的引入了 
    
     {
            test: /\.js$/,
            exclude: /node_modules/, // 一定要排除, 不检查node_modules里的模块
            use: [
              {
                loader: "babel-loader",
                options: {
                  // 预设: 指示babel做怎么样的兼容处理
                  presets: [
                    [
                      "@babel/preset-env",
                      {
                        // 按需加载
                        useBuiltIns: "entry",
                        // 指定corejs版本
                        corejs: {
                          version: 3
                        },
                        // 指定兼容性做到哪个版本浏览器
                        targets: {
                          chrome: "60",
                          firefox: "60",
                          ie: "9",
                          safari: "10",
                          edge: "17"
                        }
                      }
                    ]
                  ],
                  plugins: ["@babel/plugin-transform-runtime"]
                }
              }
            ]
     }
    
    
    4. eslint-loader和babel-loader执行顺序
    /*
    	正常来讲, 一个文件只能被一个loader来处理.
    	当一个文件要被多个loader处理的话 , 那么一定要指定loader的执行顺序: 先执行eslint , 后babel
    	给eslint-loader加上 enforce: 'pre' 属性
    */
     {
            test: /\.js$/,
            exclude: /node_modules/, // 一定要排除, 不检查node_modules里的模块
            enforce: 'pre' ,         // 优先执行, 其他loader都往后稍稍
            loader: "eslint-loader",
            options: {
              // 自动修复eslint的错误
              fix: true
            }
          }
    
    
    5. js和html的压缩
    // js 
     改成production模式就能自动压缩js 
    
    // html
     new HtmlWebpackPlugin({
          // 模版 : 将路径中的html文件作为模版复制 , 并添加引入打包输出的所有资源 css/js
          template: "./src/index.html",
          minify: {
              removeComments: true, // 清理注释
              collapseWhitespace: true // 清理空格
         	}
        })
    
    

    Ⅲ. Webpack性能优化 (重点)

    1. 开发环境性能优化
    优化点 : 1.打包构建速度   2.代码调试
    
    1.1 热模块替换 (HMR)
    hot: true
    
    
    • 样式文件 : 默认可以使用HMR功能 , 因为style-loader内部实现了 , 所以开发环境可以用style-loader方便调式 , 生产环境就得把css文件单独提取出来再上线 , 不能使用style-loader

    • js 文件 : 默认不能使用HMR功能 --> 需要添加支持HMR的代码

      ```js
        
      

      // 首先要知道入口js文件是没办法做HMR优化的 , 入口文件js代码一旦改变,所有文件都会重新加载 // 添加代码如下 : if(module.hot){ // 一旦module.hot为true, 说明开启了HMR功能 ==> 让HMR功能代码生效 module.hot.accept("./print.js",function(){ // 方法会监听print.js文件的变化 , 一旦变化,其他模块不会重新打包构建 // 会执行callback print(); }) } ```

    • html 文件 : 默认不能使用HMR功能 , 同时会导致问题 , html文件不能热更新了~ (不用做HMR功能)

      解决:修改entry入口, 将html文件引入

    1.2. source-map
    devtool:'source-map'
    
    // 
    
    
    • source-map : 1.内部 2.提示错误代码准确信息 和 源代码的错误位置
    • inline-source-map : 1.只生成一个内联的source-map 2.同上 hidden-source-map : 1.外部生成 2.不能追踪源代码错误 .只能提示到构建后代码的错误位置
    • eval--source-map : 1.内部 每一个文件都生成对应的source-map 2.提示错误代码准确信息 和 源代码的错误位置
    • nosource-source-map : 1.生成外部 2.错误代码准确信息,但是没有任何源代码信息
    • cheap-source-map : 1.生成外部 2.提示错误代码准确信息 和 源代码的错误位置 ,但只能精确到行, 不能精确到列
    • cheap-module--source-map : 1.生成外部 2. 同上 3. module会把loader的source map加进来
    // 外部和内联的区别 : 1.外部生成了文件,内联没有  2.内联构建的速度更快
    
    

    以上几种方案用法 :

    • 开发环境要求 : 速度快 , 调试更友好

      ---> eva-source-map / eval-cheap-module-source-map

    • 生产环境要求 : 源代码要不要隐藏 ? 调试要不要更友好 ?

      内联会让代码体积变大 , 所以一般不用内联

      ---> source-map / cheap-module--source-map

      如果需要隐藏源代码 , 就 nosource-source-map( 全部隐藏 ) / hidden-source-map( 只隐藏源代码, 会提示构建后代码错误信息 )

    2. 生产环境性能优化
    优化点 : 1.打包构建速度   2.代码运行性能   
    
    
    2.1 oneOf
    oneOf数组里的loader规则: 只会匹配一个 , 比如css文件匹配到css-loader以后 , 就不会在去查询匹配其他loader了 , 性能就更好
    
    

    注意 : 数组里不能有两个loader处理同一种类型文件 , 比如eslint-loader , babel-loader不能同时放在里面 , 把eslint-loader提取到外面

    2.2 缓存
    • babel缓存

      cacheDirectory: true
        
      
    • 文件资源缓存

      ​ hash 值命名后缀

      问题 : 因为 js和css构建时候生成唯一一个hash值 , 如果重新打包会使缓存失效

      ​ chunkhash: 根据chunk生成的hahs值 . 如果打包来源同一个chunk , 那么hash值就一样

      ​ contenthash:

    Ⅳ. Webpack补充详解

    1. entry 多入口
    • array : 只会形成一个chunk和一个bundle.js

      • 作用 : 只有在HMR功能中html热更新生效
    • object : 有几个入口文件就形成几个chunk , 输出几个bundle文件 ,此时的chunk名称就是 key

      entry: {
          a: "./src/test.js",          // 生成a.js
          b: "./src/index.js"          // 生成b.js
        },
        
      
      • 特殊用法 : 对象的value可以是一个数组 , 包含多个文件路径 , 将多个文件打包输出一个bundle
    2. output
    filename: 'js/[name].js'      // 指定名称 + 目录
    publicPath:'/'                // 所有资源引入的公共路径前缀
    chunkFilename: '[name]_chunk.js'  // 对非入口chunk进行重命名
    library: '[name]'             // 将打包后的js文件代码赋值给一个变量并抛出(变量名就是[]中的name)
    libraryTarget: 'window'     // 变量名添加到哪个上
    
    
    3. loader
    exclude: /node_modules/      // 排除
    include: path.resolve(__dirname,'src')   // 只检查src文件夹
    enforce: 'pre'               // 优先执行 , post -> 最后执行 , 其他就中间执行
    
    
    4. resolve
    resolve: {
        // 配置路径别名 , 简写路径 比如 src --> @
        alias: {
            $css: path.resolve(__dirname,'src/css')
        },
        // 配置省略文件路径的后缀名
        extensions: ['.js','.json'],
        // 直接告诉 webpack去哪个目录找解析模块
        modules: [path.resolve(__dirname,'../../node_modules'),"node_modules"]
    }
    
    
    5. devServer
    watchContentBase: true,      // 监视contentBase下的文件 , 一旦变动就reload
    watchOptions:{
        ignored: /node_modules/  // 忽略文件
    },
    clientLoginLevel: 'none',    // 不显示启动服务器日志信息
    quiet: true ,                // 除了一些基本启动信息以外 , 其他内容都不要显示
    overlay: false,               // 如果出错了不要全屏提示
    proxy:{                       // 反向代理
        '/api':{
            // 一旦devServer接收到'/api'开头的请求,就把请求转发到如下服务器
            target: 'http://localhost:3000',
            // 发送请求时 , 请求路径重写 : 将'/api/xxx' --> '/xxx'
            pathRewrite: {
                '^/api':''
            }
        }
    }
    
    
    6. opnimization

    起源地下载网 » webpack4.0笔记

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元