• webpack构建vue项目 基础07之开发环境、生产环境、配置的抽离


    webpack构建vue项目 基础07之开发环境、生产环境、配置的抽离

    01:webpack构建vue项目 基础07之开发环境 - 开发服务器 ( 实现页面刷新)

    package.json

    • 修改点:"dev": "webpack-dev-server --mode development",
    • 修改点:"webpack-dev-server": "^3.2.1"
      "scripts": {
        "dev": "webpack-dev-server --mode development",
        "build": "webpack --mode production",
      },
     "devDependencies": {
        "webpack": "^4.29.6",
        "webpack-cli": "^3.2.3",
        "webpack-dev-server": "^3.2.1"
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    webpack.config.js

    module.exports = {
      // webpack执行打包的唯一入口
      entry: {
        main: [path.resolve(__dirname, './src/main.js')],
      },
      // 打包的输入
      output: {
        publicPath: '', //
        // 将所有依赖的模块合并输出到main_xxxxxx.js,xxxxxx为随机生成的6位hash码
        //当内容有改变时,hash会变化,防止缓存原因导致修改不更新
        filename: 'js/[name]_[contenthash:6].js',
        // 输出文件的存放路径, 必须是绝对路径
        path: path.resolve(__dirname, "./dist")
    
      },
      // 本地开发环境配置
      devServer: {
        contentBase: path.resolve(__dirname, "./dist"), //指定被访问html页面所在的目录的
        open: true, // 指运行npm run server指令后,自动在浏览器里打开一个页面
        port: 8081, // 指定打开的页面的端口为8081,也可以指定其他端口
        inline: true, // 页面实时刷新
        // host:"127.0.0.1" // 地址 http://127.0.0.1:8081/
        overlay: true, // 如果代码出错,会在浏览器页面弹出“浮动层”。类似于 vue-cli 等脚手架
        proxy: {
          // 跨域代理转发
          '/api': {
            target: 'http://102.03.34.58',
            pathRewrite: {
              '^/api': ''
            }
          }
        },
        historyApiFallback: {
          // HTML5 history模式
          rewrites: [{
            from: /.*/,
            to: '/index.html'
          }]
        }
      },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    mian.js

    // 全局引入
    // import '@babel/polyfill'
    console.log("main");
    import {
      age
    } from "./person"
    console.log("age", age);
    let a = 10;
    console.log("a", a);
    const set = new Set([1, 2, 3, 1])
    console.log('res,', set, '; set-arr', [...set]) // res, Set(3) {1, 2, 3} ; set-arr (3) [1, 2, 3]
    import "./css/main.css"
    import "./css/index.scss"
    import {
      add
    } from "./utils/index"
    console.log("add", add(2, 2)); // add 4
    import _ from "lodash"
    console.log("使用lodash", _.add(22, 33)); // 使用lodash 55
    
    import Vue from "vue"
    import App from "./App.vue";
    
    const app = new Vue({
      el:'#app',
      render: (h) => h(App), //h就是vue中的createApp参数
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    App.vue

    <template>
      <div id="app">
        <div class="bg">msg - {{ msg }}</div>
        <div class="box">我是box-11-1</div>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          msg: 'msg-msg-1'
        }
      }
    }
    </script>
    <style scoped>
    #app {
      font-size: 40px;
    }
    .bg {
      background: yellow;
    }
    .box{
      width: 100px;
      height: 100px;
      background: pink;
      font-size: 20px;
    }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    index.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    
    <body>
      <div id="app">
      </div>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    npm run dev 效果

    • 于终端起一个服务,点击链接,可加载出开发时的代码效果
      在这里插入图片描述

    • 页面效果
      在这里插入图片描述

    npm run build 效果

    在这里插入图片描述
    在这里插入图片描述

    02:webpack构建vue项目 基础07之 开发环境、生产环境的抽离

    package.json

      "scripts": {
        "dev": "webpack-dev-server --config ./build/webpack.config.dev.js",
        "build": "webpack --config ./build/webpack.config.prod.js",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "devDependencies": {
        "webpack-merge": "^4.2.1"
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    02-1:抽离基础配置 build / webpack.config.base.js

    const path = require("path");
    const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将 css 单独打包成文件
    const HtmlWebpackPlugin = require('html-webpack-plugin') // 自动引入文件 插件
    const {
      CleanWebpackPlugin
    } = require('clean-webpack-plugin') // 版本为2.0.0 不需要 { CleanWebpackPlugin } 结构! 大于2.0.0则需要
    
    module.exports = {
      // webpack执行打包的唯一入口
      entry: {
        // main: [path.resolve(__dirname, './src/main.js')],
        main: "./src/main.js"
      },
      // 打包的输入
      output: {
        publicPath: '', //
        // 将所有依赖的模块合并输出到main_xxxxxx.js,xxxxxx为随机生成的6位hash码
        //当内容有改变时,hash会变化,防止缓存原因导致修改不更新
        filename: 'js/[name]_[contenthash:6].js',
        // 输出文件的存放路径, 必须是绝对路径
        path: path.resolve(__dirname, "../dist") // path.resolve(__dirname, "./dist")
    
      },
      // loader相关配置
      module: {
        rules: [{
            test: /\.(sa|sc|c)ss$/, // 针对 .sass .scss 或者 .css 后缀的文件设置 loader
            use: [{
                loader: "vue-style-loader"
              },
              // MiniCssExtractPlugin.loader,
              {
                loader: MiniCssExtractPlugin.loader
              },
              'css-loader',
              'postcss-loader', // 使用 postcss 为 css 加上浏览器前缀
              'sass-loader' // 使用 sass-loader 将 scss 转为 css
            ]
          },
          {
            test: /\.js$/, // 使用正则来匹配 js 文件
            exclude: /node_modules/, // 排除依赖包文件夹
            use: {
              loader: 'babel-loader' // 使用 babel-loader
            }
          },
          {
            test: /\.(png|jpg|jpeg|gif|webp)$/,
            use: [{
                loader: 'url-loader',
                options: {
                  name: '[name]-[hash:5].min.[ext]',
                  outputPath: 'images/', //输出到 images 文件夹
                  limit: 20000 //把小于 20kb 的文件转成 Base64 的格式
                }
              },
              // 使用 image-webpack-loader 对图片进行压缩
              {
                loader: "image-webpack-loader",
                options: {
                  mozjpeg: {
                    progressive: true,
                    quality: 65
                  },
                  optipng: {
                    enabled: false
                  },
                  pngquant: {
                    quality: '65-90',
                    speed: 4
                  },
                  gifsicle: {
                    interlaced: false
                  },
                  webp: {
                    quality: 75
                  }
                }
              },
            ]
          },
          {
            test: /\.vue$/,
            loader: 'vue-loader'
          },
        ]
      },
      resolve: {
        extensions: ['.js', '.css', '.scss', '.vue', '.json'], // 引入的时候 可以省略后缀
        alias: {
          'vue$': 'vue/dist/vue.esm.js'
        }
      },
      plugins: [
        //默认情况下,此插件删除 webpack output.path目录中的所有文件,以及每次成功重建后所有未使用的 webpack 资产
        new CleanWebpackPlugin(),
        // 自动生成html ( 于打包后 dist目录下的 双击在浏览器显示 )
        new HtmlWebpackPlugin({
          // 打包输出HTML
          title: '自动生成 HTML',
          minify: {
            // 压缩 HTML 文件
            removeComments: true, // 移除 HTML 中的注释
            collapseWhitespace: true, // 删除空白符与换行符
            minifyCSS: true // 压缩内联 css
          },
          filename: 'index.html', // 生成后的文件名
          template: 'index.html', // 根据此模版生成 HTML 文件
          // chunks: ['main'] // entry中的 app 入口才会被打包
        }),
        // 分割css
        new MiniCssExtractPlugin({
          filename: '[name].css',
          chunkFilename: '[id].css'
        }),
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117

    02-2:抽离开发环境 build / webpack.config.js

    const path = require("path");
    const merge = require("webpack-merge")
    const baseConfig = require("./webpack.config.base")
    const devConfig = {
      output: {
        filename: '[name].js',
        chunkFilename: '[name].js'
      },
      mode: 'development',
      devtool: 'source-map', // 调试源码
      // 本地开发环境配置
      devServer: {
        contentBase: path.resolve(__dirname, "../dist"), //指定被访问html页面所在的目录的
        open: true, // 指运行npm run server指令后,自动在浏览器里打开一个页面
        port: 8081, // 指定打开的页面的端口为8081,也可以指定其他端口
        inline: true, // 页面实时刷新
        // host:"127.0.0.1" // 地址 http://127.0.0.1:8081/
        overlay: true, // 如果代码出错,会在浏览器页面弹出“浮动层”。类似于 vue-cli 等脚手架
        proxy: {
          // 跨域代理转发
          '/api': {
            target: 'http://102.03.34.58',
            pathRewrite: {
              '^/api': ''
            }
          }
        },
        // historyApiFallback: true
        historyApiFallback: {
          // HTML5 history模式
          rewrites: [{
            from: /.*/,
            to: '/index.html'
          }]
        }
      },
      // module: {
      //   rules: [{
      //     test: /\.(sa|sc|c)ss$/, // 针对 .sass .scss 或者 .css 后缀的文件设置 loader
      //     use: [
      //       'style-loader',
      //       {
      //         loader: "vue-style-loader"
      //       },
      //       {
      //         loader: MiniCssExtractPlugin.loader
      //       },
      //       'css-loader',
      //       'postcss-loader', // 使用 postcss 为 css 加上浏览器前缀
      //       'sass-loader' // 使用 sass-loader 将 scss 转为 css
      //     ]
      //   }]
      // }
    }
    module.exports = merge(baseConfig, devConfig)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    02-3:抽离生产环境 build/webpack.config.js

    const path = require("path");
    const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将 css 单独打包成文件
    const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') // 压缩 css
    const HtmlWebpackPlugin = require('html-webpack-plugin') // 自动引入文件 插件
    const {
      CleanWebpackPlugin
    } = require('clean-webpack-plugin') // 版本为2.0.0 不需要 { CleanWebpackPlugin } 结构! 大于2.0.0则需要
    
    // 去掉 不加载的css
    const PurifyCSS = require('purifycss-webpack')
    const glob = require('glob-all')
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); //压缩js
    
    const merge = require("webpack-merge")
    const baseConfig = require("./webpack.config.base")
    
    const prodConfig = {
      mode: 'production',
      // 代码切片相关
      optimization: {
        // 代码切片 分割 打包后分割为多个 .js文件
        splitChunks: {
          chunks: 'all',
          // 打包后的效果
          // js/lodash_950848.js  71.1 KiB       0  [emitted]  lodash
          // js/main_63de8b.js  1.78 KiB       1  [emitted]  main
          // js/vendors~main_2938f3.js   112 KiB       2  [emitted]  vendors~main
          cacheGroups: {
            lodash: {
              name: 'lodash',
              test: /[\\/]node_modules[\\/]lodash[\\/]/,
              priority: 5 // 优先级要大于 vendors 不然会被打包进 vendors
            },
            vendors: {
              test: /[\\/]node_modules[\\/]/,
              priority: -10 // 打包node_modules
            },
            default: {
              minChunks: 2,
              priority: -20,
              reuseExistingChunk: true
            }
          }
        },
    
      },
      plugins: [
        //默认情况下,此插件删除 webpack output.path目录中的所有文件,以及每次成功重建后所有未使用的 webpack 资产
        new CleanWebpackPlugin(),
        // 清除无用 css
        new PurifyCSS({
          paths: glob.sync([
            // 要做 CSS Tree Shaking 的路径文件
            path.resolve(__dirname, './*.html'), // 请注意,我们同样需要对 html 文件进行 tree shaking
            path.resolve(__dirname, './src/*.js')
          ])
        }),
        // // 分割css
        // new MiniCssExtractPlugin({
        //   filename: '[name].css',
        //   chunkFilename: '[id].css'
        // }),
        // 压缩css
        new OptimizeCssAssetsPlugin({
          assetNameRegExp: /\.optimize\.css$/g,
          cssProcessor: require('cssnano'),
          cssProcessorPluginOptions: {
            preset: ['default', {
              discardComments: {
                removeAll: true
              }
            }],
          },
          canPrint: true
        }),
        // 压缩js
        new UglifyJsPlugin(),
      ]
    }
    module.exports = merge(baseConfig, prodConfig)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    App.vue

    <template>
      <div id="app">
        <div class="bg">msg - {{ msg }}</div>
        <div class="box">我是box-11-1-111-1</div>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          msg: 'msg-msg-1'
        }
      }
    }
    </script>
    <style scoped>
    #app {
      font-size: 40px;
    }
    .bg {
      background: yellow;
    }
    .box{
      width: 100px;
      height: 100px;
      background: pink;
      font-size: 20px;
    }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    mian.js

    // 全局引入
    // import '@babel/polyfill'
    console.log("main");
    import {
      age
    } from "./person"
    console.log("age", age);
    let a = 10;
    console.log("a", a);
    const set = new Set([1, 2, 3, 1])
    console.log('res,', set, '; set-arr', [...set]) // res, Set(3) {1, 2, 3} ; set-arr (3) [1, 2, 3]
    import "./css/main.css"
    import "./css/index.scss"
    import {
      add
    } from "./utils/index"
    console.log("add", add(2, 2)); // add 4
    import _ from "lodash"
    console.log("使用lodash", _.add(22, 33)); // 使用lodash 55
    
    import Vue from "vue"
    import App from "./App.vue";
    
    const app = new Vue({
      el:'#app',
      render: (h) => h(App), //h就是vue中的createApp参数
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    npm run dev 效果

    在这里插入图片描述

    npm run build 效果

    在这里插入图片描述

    index.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    
    <body>
      <div id="app">
      </div>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    .babelrc

    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "useBuiltIns": "usage",
            "corejs": 3
          }
        ]
      ],
      "plugins": ["@babel/plugin-transform-runtime"]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    postcss.config.js

    module.exports = {
      plugins: [
        require('autoprefixer')
        // , require('postcss-pxtorem')({
        //   remUnit: 50, // 50px = 1rem
        //   remPrecision: 2 // rem的小数点后位数
        // })
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    css

    mian.css
    body {
      /* background: yellow; */
       /* 29kb  效果 background: url(images/dog1-afa6a.min.webp); */
      background: url("../img/dog.webp");
      /* 4.4kb 效果 background: url(data:image/webp;base64,UklGRpYRA。。。。 */
      /* background: url("../img/hlw.webp") */
      /* 注意点:配置了图片的大小压缩 小于20kb 转化为base64 */
    }
    
    index.scss
    $bgColor: red !default;
    html {
      p {
        background-color: $bgColor;
      }
      .ppp {
        display: flex;
        justify-content: flex-end;
        color: #fff;
        font-size: 16px;
        border: 2px solid #ccc;
      }
      .box {
        width: 100px;
        height: 100px;
        border: 2px solid red;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    centos7安装chrome/Firefox浏览器
    通用Mapper获取数据表中id为0解决方法。千万别瞎改int为integer了
    社会统计课程笔记
    高级数据结构——海量数据(位图,布隆过滤器)
    vue中使用 eslint+prettier
    如何做代码评审?
    Debian篇——系统安装在SD卡上如何调整系统分区大小
    数据结构与算法简介
    .NET Core 实现后台任务(定时任务)Longbow.Tasks 组件(三)
    【数据挖掘】滴滴公司数据挖掘工程师笔试题
  • 原文地址:https://blog.csdn.net/weixin_43845137/article/details/126302297