• webpack4搭建vue多页面环境


    总结一下webpack4配置vue开发环境,本文不具体介绍webpack的基本概念和用途,如有不了解的请参见https://www.webpackjs.com/concepts/官网

    一、webpack基本环境配置

    本机系统:centOS、node版本:v10.19.0、npm版本:6.13.4

    1、创建项目

    mkdir vuepro //创建项目目录
    cd vuepro
    npm init

    npm init 之后一路回车创建好项目

    2、配置webpack

    npm i webpack webpack-cli -D 
    mkdir src              //创建src和config目录,并创建对应文件
    touch src/index.js
    mkdir config
    touch config/webpack.common.js

    3、webpack.common.js文件基本配置

    const path = require('path');
    module.exports = {
        mode:'development', 
        entry: path.resolve(__dirname,'../src/index.js'),   
        output: {
            filename: '[name].[hash:4].js',      // 打包后的文件名称
            path: path.resolve(__dirname,'../dist')  // 打包后的文件目录
        }
    }

    并且在package.json中加上打包执行的文件:

     index.js里随便写一些js内容如:

    执行:

    npm run build

    控制台成功打包并输出在dist文件下

    4、清空打包目录

    npm i clean-webpack-plugin -D
    const  { CleanWebpackPlugin } = require('clean-webpack-plugin')
    new CleanWebpackPlugin()

    5、配置html模板

    npm i html-webpack-plugin -D
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    new HtmlWebpackPlugin({
        title: 'index',
        filename: 'index.html',
        template:path.resolve(__dirname,'../template/index.html')
    }) 
    
    mkdir template
    touch temloate/index.html        

    并在index.html中写入基本的html骨架,此时的webpack.common.js:

    const path = require('path');
    const  { CleanWebpackPlugin } = require('clean-webpack-plugin')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    module.exports = {
        mode:'development', 
        entry: path.resolve(__dirname,'../src/index.js'),   
        output: {
            filename: '[name].[hash:4].js',      // 打包后的文件名称
            path: path.resolve(__dirname,'../dist')  // 打包后的文件目录
        },
        plugins:[
            new CleanWebpackPlugin(),
           new HtmlWebpackPlugin({
              title: 'index',
              filename: 'index.html',
              template:path.resolve(__dirname,'../template/index.html')
            })
        ]
    }

    此时运行npm run build 在dist目录上应该生成一个html文件和一个js文件,并且js文件直接注入了html中

     在浏览器打开index.html并打开控制台,就能看到我们在js里写的conso语句已经执行了

     

     我们配置的mode:'development'在js里是能通过process.env.NODE_ENV获取到的;但是在配置文件里,我们是访问不到process.env.NODE_ENV的比如,在webpack.common.js加入

    然后执行npm run build  

    可见在process.env里是没有NODE_ENV变量的

    6、配置cross-env定义环境变量

    npm i -D cross-env
    //把package.json的buil改为
    "build": "cross-env NODE_ENV=development webpack --config config/webpack.common.js"

    此时在执行npm run build 配置文件里就能访问到process.env.NODE_ENV了

     从这里开始不再一步一步搭建,而是直接使用我搭建好的配置,完整的配置地址:https://github.com/jiangconghu01/webpackpro.git

    7、配置moudle处理css并分离

    npm i style-loader css-loader mini-css-extract-plugin -D
    const MiniCssExtractPlugin = require("mini-css-extract-plugin")
    const isDev = process.env.NODE_ENV === 'development'
    
        module: {
            rules: [
            {
                test: /.css$/,
                use: [
                    isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
                    'css-loader' 
                  ]
            }]
        }

    8 、处理js

    可以转化es6之后新语法为浏览器可执行的es5语法,并且在使用新的api和内置对象可以自动polyfill;当然之前使用

    1.import "babel-polyfill";

    2.module.exports {

      entry["babel-polyfill""./app/js"]

    };

    这种方式全局注入也是可以的,不过这里不使用这种方式

    npm i babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
    npm i core-js@2 -S
            {   
                test: /.js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                  loader: 'babel-loader',
                  options: {
                    presets:[
                        ['@babel/preset-env',{"useBuiltIns": "usage","corejs": 2}]//这里要加[],要不会报错
                    ],
                    plugins:["@babel/plugin-transform-runtime"]
                  }
                }            
            },

    具体的babel7的配置参考:https://juejin.im/post/5ddff3abe51d4502d56bd143

     9、处理scss文件

    npm i autoprefixer node-sass sass-loader postcss-loader -D
            {
                test: /.scss$/,
                use: [isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
                    'css-loader',
                    {
                      loader:'postcss-loader',
                      options:{
                          plugins:[require('autoprefixer')]
                      }
                    },
                    'sass-loader'
                ]
            }

    并使用autoprefixer自动注入浏览器兼容前缀,配置之后在package.json中加入

    browerslist配置就能自动注入前缀了,具体配置规则可以看https://www.npmjs.com/package/browserslist

    10、处理图片,字体文件等配置

    npm i url-loader file-loader -D
            {
              test: /.(png|svg|jpg|jpeg|gif)$/,
              use: [{
                loader: 'url-loader',
                options: {
                  esModule: false,
                  limit: 1024 * 3, // 3k一下的图片转为bs64编码
                  name: 'resources/[name].[hash:8].[ext]'
                }
              }
              ]
            },
            {
              test: /.(woff|woff2|eot|ttf|otf)$/,
              use: [{
                loader: 'file-loader',
                options: {
                  limit: 1024,
                  name: 'resources/[name].[hash:8].[ext]'
                }
              }

    11、使用开发服务器webpakc-dev-server

      mode: 'development',
      devServer: {
        contentBase: path.join(__dirname, '../dist'),
        index: 'proindex.html',
        compress: true,
        hot: true,
        host: '0.0.0.0',
        port: 9000,
        proxy: {
          '/czxt': {
            target: 'http://39.105.122.153:3000',
            changeOrigin: true,
            secure: false
          }
        }
      }

    这里proxy配置改写不同接口和地址

    12、处理vue文件

    npm i vue-loader -D
    const VueLoaderPlugin = require('vue-loader/lib/plugin')
    new VueLoaderPlugin()
    {
        test:/.vue$/,
        use:['vue-loader']
     }

    13、配置resolve

    配置可以省略后缀,还有经常饮用文件路径的别名,提高代码书写效率

        resolve: {
            extensions: [".json", ".js", ".jsx",".vue"],
            alias: {
              "@": path.join(__dirname, "../src"),
              'pages': path.join(__dirname, "../src/pages")
            }
          }

    14、配置打包显示进度和时间,配置打包分析结果

    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
    const ProgressBarPlugin = require('progress-bar-webpack-plugin')
        new ProgressBarPlugin({  // 显示进度
          format: chalk.green('Progressing') +  '[:bar]' + chalk.green(':percent') + '(:elapsed seconds)',
          clear: false
        }),
        new BundleAnalyzerPlugin({
          openAnalyzer: false,
          analyzerMode: 'static',
          reportFilename: 'bundle_analyzer_report.html'
        })

    到这里基本配置的内容都差不多了

    二、优化配置

    1、为了减少打包体积,压缩文件

     1.1、 压缩图片:之前的配置里,处理图片的url-loader对小图(limit限制大小)转化为base64编码减少请求,在此之前我们先使用mage-webpack-loader

    对图片压缩

    brew install libpng //先装libpng,brew是mac的安装工具
    cnpm install image-webpack-loader -D//npm 没安成功,我换了cnpm
        {
              test: /.(png|svg|jpg|jpeg|gif)$/,
              use: [{
                loader: 'url-loader',
                options: {
                  esModule: false,
                  limit: 1024 * 3, // 3k一下的图片转为bs64编码
                  name: 'resources/[name].[hash:8].[ext]'
                }
              },
              {    // 压缩图片
                loader: 'image-webpack-loader',
                options: {
                  disable: false
                }
              }]
        }

    可以对比小配置前后的打包大小,比如这个titile的png图片:不压缩之前

    配置压缩以后:

     原来10.5k,现在5.94k

    1.2、 压缩css

    npm i optimize-css-assets-webpack-plugin -D
    const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
        new MiniCssExtractPlugin({
          filename: 'css/[name].style.css'
        }),
        new OptimizeCSSAssetsPlugin({
          assetNameRegExp: /.style.css$/g,
          cssProcessor: require('cssnano'),
          cssProcessorOptions: { safe: true, discardComments: { removeAll: true } },
          canPrint: true
        }),

    根据前边的module里css和scss的配置

     分离出来的css都放在(filename: 'css/[name].style.css')css文件夹下,并且有.style.css命名规则,所以配置压缩范围:assetNameRegExp: /.style.css$/g

    1.3、 压缩js

    webpack4直接配置

    mode: 'production'
    就能压缩js了
     
    2、提取公共代码
          optimization:{
            splitChunks: {  
              cacheGroups: {  
    
                  commons: {  
                      name: "commons",
                      chunks: "initial",  
                      minSize:0,      //代码最小多大,进行抽离
                      minChunks:2,    //代码复 2 次以上的抽离
                      priority: 1 
                  },
                  vendors: { 
                      test: /node_modules/,
                       name: 'vendors', 
                       minSize: 0,
                        minChunks: 1, 
                        chunks: 'initial',
                        priority: 10 
                 }
              }
           }
          }

    提取所有node_modules里的库代码到vendors里,提取代码里的公共代码到common里,当然这样也有问题,在引入很多不同的库时候,就是vendors会很大

    所以这里有两个问题:

    1)、每次打包都要打包node_modules目录下引入的库和框架代码,打包速度特别慢

    2)、vendors文件很大,页面加载慢,等待时间长

    1、针对打包速度慢的问题,可以使用DllPlugin DllReferencePlugin插件将node_modules下的框架和库代码打包成一个文件,直接引入html模板里,这样只要版本不变,不用每次打包node_modules下的文件,提高了打包速度;但是没有解决vendors特别大的问题,当然也可以每个库单独打包引入,但是这样特别麻烦,多页面时候,每个html都要引入

    2、针对vendors很大的问题,可以像下边这样把库都分开打包,分开引入,但是这样打包速度提不上了

     还有就是引用cdn资源了,既能提高打包速度,又不用吧第三方库打包成很大的vendors,还能提高加载速度

    在html中引入

     然后配置

          externals: {
              'vue': 'Vue',
              'vue-router': 'VueRouter',
              'vuex': 'Vuex',
              'echarts': 'echarts',
              'axios': 'axios'
          },

    把项目文件里的这些库的引入全部去掉

    原来打包速度:

     不用打包框架和库代码之后:

    3、多页配置

    一般,在entry加多个入口,然后每个入口对应一个html,每次新加一个文件时候就在配置文件加一个入口,然后new一个HtmlWebpackPlugin,当页面很多时候你就得反复修改配置文件,所以我我们借助node的glob模块对项目下的文件进行遍历,动态输出配置入口和plugin

    const glob = require('glob')
    const path = require('path')
    const entryFile = glob.sync(path.join(__dirname,'../src/*.js'))
    
    const HtmlWebpackPlugin=require('html-webpack-plugin');
    
    const entry = {}
    const htmlWebpackPlugins = []
    entryFile.forEach(file => {
      const filename = path.basename(file.split('/').pop(), '.js')
      entry[filename] = [file],
      htmlWebpackPlugins.push(
        new HtmlWebpackPlugin({
          title: filename,
          chunks:['vendors','commons',filename],
          template: path.resolve(__dirname,`../template/${filename}.html`),
          filename: `${filename}.html`
        })
      )
    })
    console.log(entry)
    module.exports = {
      entry,
      plugins:htmlWebpackPlugins
    }

    现在只要每次在src下创建入口文件,然后在template文件下创建对应的html模板文件就行。

     4、懒加载的配置

    npm i @babel/plugin-syntax-dynamic-import -D
            {   
                test: /.js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                  loader: 'babel-loader',
                  options: {
                    presets:[
                        ['@babel/preset-env',{"useBuiltIns": "usage","corejs": 2,modules: false}]//这里要加[],要不会报错
                    ],
                    plugins:["@babel/plugin-transform-runtime",'@babel/plugin-syntax-dynamic-import']
                  }
                }            
            }

    修改代码中如路由为动态加载

    5、缓存打包结果,提高编译效率

    npm i cache-loader -D

    添加cache-loader之后再次启动开发环境也变快了,第二次编译只用了

    当然,用了测试的这个demo项目就十多个文件,几百行代码

    注:本次测试所有文件地址:https://github.com/jiangconghu01/webpackpro.git 

    
    
    
  • 相关阅读:
    工厂模式
    将博客搬至CSDN
    网络安全-跨站脚本攻击XSS(Cross-Site Scripting)
    Linux 权限
    git常用的语句
    git代码提交与克隆
    git学习
    Mybatis常见问题
    关于集合常见的问题
    远程连接(加密验证问题解决)
  • 原文地址:https://www.cnblogs.com/yifeng555/p/12356631.html
Copyright © 2020-2023  润新知