webpack5构建一个小型简单vue项目 (练习)

举报
代码哈士奇 发表于 2022/01/31 08:34:07 2022/01/31
【摘要】 webpack5构建一个小型简单vue项目 (练习)

webpack5构建vue

必要环境

安装ndejs

我们需要安装node 如果没有安装则安装 安装过则跳过

下载安装nodejs

执行

node -v
npm -v

在这里插入图片描述

初始化项目文件夹

新建一个空的项目

执行 npm init -y 初始化

npm init -y

会生成一个package.json
在这里插入图片描述

安装webpack以及 html-webpack-plugin

控制台执行

npm i webpack webpack-cli webpack-dev-server html-webpack-plugin -D

安装babel-loader

babel可以将我们的代码向下适配

npm i babel-loader @babel/core @babel/preset-env @babel/polyfill core-js@3 -D

安装 css-lodaer

支持less

npm install css-loader style-loader sass-loader postcss-loader autoprefixer less-loader  -D

安装 mini-css-extract-plugin css-minimizer-webpack-plugin

用来抽离压缩css 代码

npm i mini-css-extract-plugin css-minimizer-webpack-plugin -D

项目依赖 (面还有需要安装的)

 "devDependencies": {
    "@babel/core": "^7.16.12",
    "@babel/polyfill": "^7.12.1",
    "@babel/preset-env": "^7.16.11",
    "@element-plus/icons": "^0.0.11",
    "@vue/cli-plugin-babel": "^4.5.15",
    "@vue/compiler-sfc": "^3.2.29",
    "autoprefixer": "^10.4.2",
    "babel-eslint": "^10.1.0",
    "babel-loader": "^8.2.3",
    "copy-webpack-plugin": "^10.2.1",
    "core-js": "^3.20.3",
    "css-loader": "^6.5.1",
    "css-minimizer-webpack-plugin": "^3.4.1",
    "element-plus": "^1.3.0-beta.9",
    "eslint": "^7.32.0",
    "eslint-loader": "^4.0.2",
    "eslint-plugin-vue": "^8.4.0",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^5.5.0",
    "less-loader": "^10.2.0",
    "lodash": "^4.17.21",
    "mini-css-extract-plugin": "^2.5.3",
    "postcss-loader": "^6.2.1",
    "sass": "^1.26.5",
    "sass-loader": "^8.0.2",
    "style-loader": "^3.3.1",
    "terser-webpack-plugin": "^5.3.0",
    "unplugin-auto-import": "^0.5.11",
    "unplugin-vue-components": "^0.17.15",
    "url-loader": "^4.1.1",
    "vue": "^3.2.29",
    "vue-loader": "^16.1.0",
    "vue-router": "^4.0.12",
    "vue-style-loader": "^4.1.3",
    "vuex": "^4.0.2",
    "webpack": "^5.67.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.7.3"
  }

创建多个目录

创建多个文件夹 方便存放不同资源 参考vue-cli脚手架生成的

根目录下新建 webpack.config.js

src下创建main.ts 以及 App.vue

如下
在这里插入图片描述

public 目录下

我们放入一个ico文件
在这里插入图片描述

创建模板 html文件

webpack5内置了clean output开启即可

在 public目录下新建 index.html

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
    <strong><%= htmlWebpackPlugin.options.title %>:请检查js是否正常启用</strong>
</noscript>
<div id="app"></div>
</body>
</html>

开始构建vue项目

安装 vue-loader等

npm i vue-loader vue-template-compiler vue@next  vuex@next vue-router@next -D
npm install terser-webpack-plugin copy-webpack-plugin -D

配置webpack

webpack5内置了 clean 和 热更新

开启方式 在devServer配置

devServer: {
   hot: true,
   liveReload: true
},

在 webpack.config.js 文件中

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const MiniCssExtract = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') //生产环境
const TerserPlugin = require('terser-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = (env) => {
  return {
    devServer: {
      port: 8888,
      hot: true,
      liveReload: true
    },

    mode: env.development ? 'development' : 'production',

    resolve: {
      alias: {
        '@': path.resolve(__dirname, './src')
      }
    },

    entry: './src/main.js',

    output: {
      filename: "js/[name].[contenthash].js",
      // path: path.resolve(__dirname, 'dist/js'),
      clean: true,
      publicPath: "./"
    },
    module: {
      rules: [
        {
          test: /\.vue$/,
          loader: 'vue-loader'
        },
        {
          test: /\.js$/,
          exclude: file => (
            /node_modules/.test(file) &&
            !/\.vue\.js/.test(file)
          ),
          use: [
            {
              loader: 'babel-loader',
              options: {
                presets: [
                  [
                    '@babel/preset-env',
                    {
                      targets: [
                        'last 1 version', //浏览器最新的一个版本
                        '> 1%' //代码使用超过1%
                      ],
                      useBuiltIns: 'usage',
                      corejs: 3
                    }
                  ]
                ]
              }
            },
            {
              loader: "eslint-loader"
            }
          ]
        },
        {
          test: /\.(css|scss)$/,
          use: [env.development ? 'vue-style-loader'
            : MiniCssExtract.loader,
            {
              loader: 'css-loader'
            },
            {
              loader: 'sass-loader'
            }
          ]
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          type: 'asset/resource'
        },
        {
          test: /\.(png|jpg|gif)$/,
          use: [
            {
              loader: "file-loader",
              options: {
                name:'img/[name].[hash].[ext]',
              }
            }


          ]
        }
      ]
    },

    optimization: {
      minimizer: [
        new CssMinimizerPlugin(),
        new TerserPlugin()
      ]
    },

    plugins: [
      new HtmlWebpackPlugin({
        title: "小型vue应用",
        template: "public/index.html",
        filename: "index.html",
        baseUrl: './icon/favicon.ico'
      }),
      new CopyWebpackPlugin({
        patterns:[
          {
            from: path.resolve(__dirname, './public/icon'),
            to: path.resolve(__dirname, './dist/icon'),
          }
        ]
      }),
      new MiniCssExtract({
        filename: 'css/style.css'
      }),
      new VueLoaderPlugin()
    ]

  }

}

修改package.json

在这里插入图片描述

初始化 eslint

eslint --init

选择 检查找到问题

选择 js 浏览器环境 不用ts

拆分配置文件

开发环境

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  devServer: {
    port: 8888,
    hot: true,
    liveReload: true
  },

  mode: 'development',

  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  },

  entry: './src/main.js',

  output: {
    filename: "js/[name].[contenthash].js",
    // path: path.resolve(__dirname, 'dist/js'),
    publicPath: "/"
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.js$/,
        exclude: file => (
          /node_modules/.test(file) &&
          !/\.vue\.js/.test(file)
        ),
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    targets: [
                      'last 1 version', //浏览器最新的一个版本
                      '> 1%' //代码使用超过1%
                    ],
                    useBuiltIns: 'usage',
                    corejs: 3
                  }
                ]
              ]
            }
          },
          {
            loader: "eslint-loader"
          }
        ]
      },
      {
        test: /\.(css|scss)$/,
        use: ['vue-style-loader',
          {
            loader: 'css-loader'
            // ,
            // options: {
            //   modules:{
            //     localIdentName: '[local]_[hash:base64:8]'
            //   }
            // }
          },
          {
            loader: 'sass-loader'
            // options: {
            //   // sass-loader version >= 8
            //   sassOptions: {
            //     indentedSyntax: true
            //   }
            // }
          }
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource'
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          // {
          //   loader:'url-loader',
          //   options:{
          //     limit:4096,
          //     outputPath:'./img',
          //     name:'[name].[hash].[ext]',
          //   }
          // },
          {
            loader: "file-loader",
            options: {
              name:'img/[name].[hash].[ext]',
            }
          }


        ]
      }
    ]
  },

  plugins: [
    new HtmlWebpackPlugin({
      title: "小型vue应用",
      template: "public/index.html",
    }),
    new VueLoaderPlugin()
  ]

}

生产环境

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const MiniCssExtract = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') //生产环境
const TerserPlugin = require('terser-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = () => {

  return {

    mode: 'production',

    resolve: {
      alias: {
        '@': path.resolve(__dirname, './src')
      }
    },

    entry: './src/main.js',

    output: {
      filename: "js/[name].[contenthash].js",
      // path: path.resolve(__dirname, 'dist/js'),
      clean: true,
      publicPath: "./"
    },
    module: {
      rules: [
        {
          test: /\.vue$/,
          loader: 'vue-loader'
        },
        {
          test: /\.js$/,
          exclude: file => (
            /node_modules/.test(file) &&
            !/\.vue\.js/.test(file)
          ),
          use: [
            {
              loader: 'babel-loader',
              options: {
                presets: [
                  [
                    '@babel/preset-env',
                    {
                      targets: [
                        'last 1 version', //浏览器最新的一个版本
                        '> 1%' //代码使用超过1%
                      ],
                      useBuiltIns: 'usage',
                      corejs: 3
                    }
                  ]
                ]
              }
            },
            {
              loader: "eslint-loader"
            }
          ]
        },
        {
          test: /\.(css|scss)$/,
          use: [ MiniCssExtract.loader,
            {
              loader: 'css-loader'
              // ,
              // options: {
              //   modules:{
              //     localIdentName: '[local]_[hash:base64:8]'
              //   }
              // }
            },
            {
              loader: 'sass-loader'
              // options: {
              //   // sass-loader version >= 8
              //   sassOptions: {
              //     indentedSyntax: true
              //   }
              // }
            }
          ]
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          type: 'asset/resource'
        },
        {
          test: /\.(png|jpg|gif)$/,
          use: [
            // {
            //   loader:'url-loader',
            //   options:{
            //     limit:4096,
            //     outputPath:'./img',
            //     name:'[name].[hash].[ext]',
            //   }
            // },
            {
              loader: "file-loader",
              options: {
                name:'img/[name].[hash].[ext]',
              }
            }


          ]
        }
      ]
    },

    optimization: {
      minimizer: [
        new CssMinimizerPlugin(),
        new TerserPlugin()
      ]
    },

    plugins: [
      new HtmlWebpackPlugin({
        title: "小型vue应用",
        template: "public/index.html",
        filename: "index.html",
        baseUrl: './icon/favicon.ico'
      }),
      new CopyWebpackPlugin({
        patterns:[
          {
            from: path.resolve(__dirname, './public/icon'),
            to: path.resolve(__dirname, './dist/icon'),
          }
        ]
      }),
      new MiniCssExtract({
        filename: 'css/style.css'
      }),
      new VueLoaderPlugin()
    ]

  }

}

测试

文件夹的基础文件 我复制的通过vue-cli创建的项目

运行
npm run start
在这里插入图片描述

打包
npm run build
在这里插入图片描述
在这里插入图片描述

拓展

这只是一个简单的项目

我们可以增加插件等赋予它更多能力
还有很多需要优化的地方
比如配置文件可以通过合并来优化

开发环境减少插件使用等等

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。