浅谈webpack+vue从零开始的后台管理项目 ----- webpack配置及构建vue初始化项目

1,881 阅读6分钟

前言

最近在总结深入自身掌握的知识点, 然后试着从零开始构建一个完整的webpack + VUE的项目. 然后通过
项目对整体流程进行了一个归纳总结, 文章会挺长, 分篇上传吧, 内容方面就以当前在做的后台
项目为示例对象, 发表一些个人归纳的东西, 希望对大家会有一定帮助. 当然, 还是那句话, 每个人的理
解观念不同, 也希望不足的地方能够得到指出补充.

正文

使用webpack初始化构建项目

1. 生成package.json文件

npm init

2. 安装webpack

npm install -g webpack 全局安装 npm install --save-dev webpack 在本地项目中安装

3. 初步搭建项目结构


其中, dist为webpack打包后, 资源存放的文件夹
src为项目主体内容, 也就是页面,路由等开发文件夹
package.json 为当前项目总体信息
webpack.config.js 为webpack的内置配置,之后可以在这个文件中进行一些初始化配置
index.html 为项目主体html文件

  1. 初步了解webpack配置规则
    关于webpack的配置规则, 在这里就初步了解下常用的几个属性的含义和用法, 具体内容不需要太关注,
    主要是了解属性的作用
      const path = require('path');
      const webpack = require('webpack');
      //使用该插件 会清理每次打包后, 过去遗留在dist中的旧代码
      const {CleanWebpackPlugin} = require("clean-webpack-plugin");
      // 使用该插件 , 会解析vue文件
      const VueLoaderPlugin = require('vue-loader/lib/plugin');
      // 使用该插件,会自动创建并更新html文件
      const HtmlWebpackPlugin = require('html-webpack-plugin');

      module.exports = {
        // 入口,起点或是应用程序的起点入口。从这个起点开始,应用程序启动执行。如果传递一个数组,那么数组的每一项都会执行。 
        // 每个 HTML 页面都有一个入口起点。单页应用(SPA):一个入口起点,多页应用(MPA):多个入口起点。
        // 一般指向项目中,src目录下的main.js文件
          entry:{
              app:'./src/main.js'
          },
          // 输出, 指示 webpack 如何去输出、以及在哪里输出你的「bundle、asset 和其他你所打包或使用 webpack 载入的任何内容」
          // 指的是通过webpack打包后的生成的文件以什么名称, 放置在什么位置,  这里一般放置在dist目录下,
          output:{
             // 将所有依赖的模块合并输出到一个叫bundle.js文件内
              filename:'bundle.js',
              // 分别对应名称输出
              filename: '[name].[hash].js'
              // 将输出的文件都放在dist目录下
              path:path.join(__dirname,'./dist')
          },
          // 这个属性,用于设定项目中不同类型的模块所对应的处理规则, 即用到的一些, 诸如sass,less, css, vue, 图片, 文件, 都在  
          这个属性中进行设置处理规则, 当然, 都会有对应处理的loader.  loader 用于对模块的源代码进行转换
           module: {
              rules: [
                  {
                    test: /\.vue$/, // 匹配对象的后缀, 如这里匹配.vue文件
                    use: [{ // 用于转换该文件类型的loader,
                      loader: 'vue-loader',
                      options: { // 内部配置
                        loaders: {
                          'scss': 'style-loader!css-loader!sass-loader'
                        }
                      }
                    }],
                  },
                  {
                    test: /\.css$/,
                    use: ['vue-style-loader','css-loader'] // 使用vue-style-loader直接插入到style标签中
                  },
                  {
                    test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
                    loader: 'file-loader'
                  },
                  {
                    test: /\.scss$/,
                    // 这里注意一点, use为数组时, 即多loader作用时, 执行规则从后到前, 先使用数组末尾的loader执行转换
                    use: ['style-loader', 'css-loader', 'sass-loader']
                  }
              ]
          },
          // 自定义webpack构建过程, 例如,当多个 bundle 共享一些相同的依赖,使用 CommonsChunkPlugin 有助于提取这些依赖到共享的 bundle 中,来避免重复打包
          plugins:[
              new HtmlWebpackPlugin({
                  template:'index.html',
                  filename:'index.html'
              }),
              new VueLoaderPlugin(),
              new webpack.HashedModuleIdsPlugin(),
              new CleanWebpackPlugin()
          ],
          // 配置模块如何被解析, 即设定相对应模块的解析规则
          resolve: {
              // 自动补全的扩展名
              extensions: ['.js', '.vue', '.json'],
              // 默认路径代理
              // 例如 import Vue from 'vue',会自动到 'vue/dist/vue.common.js'中寻找
              // 这样可以使之后在开发项目的时候, 引用文件时不必关注不同层级的问题
              alias: {
                  '@': path.join(__dirname, './', 'src'),
                  '@api': path.join(__dirname, './', 'src/api'),
                  '@styles': path.join(__dirname, './', 'src/styles'),
                  '@config': path.join(__dirname, './', 'config'),
                  'vue$': 'vue/dist/vue.common.js',
                  '@components':path.join(__dirname, './', 'src/components')
              }
          }
      }
  1. 初步启动项目

    1. 首先将index.html内部代码完善
      <!DOCTYPE html>
        <html lang="en">
        <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
        </head>
        <body>
          <script src="/dist/build.js"></script>
        </body>
      </html>
      
    2. 在src目录下创建主体入口的main.js文件, 创建一个demo.js示例文件 demo.js示例文件中
    export default function say() {
        console.log('hello world');
    }
    

    main.js文件中

    import say from './util';
    say();
    
    1. 基本信息处理完成后, 就需要初步配置webpack文件了, 先简单的配个出口和入口
    var path = require('path');
    var webpack = require('webpack');
    
    module.exports = {
        entry: './src/main.js', // 项目的入口文件,webpack会从main.js开始,把所有依赖的js都加载打包
        output: {
            path: path.resolve(__dirname, './dist'), // 项目的打包文件路径
            publicPath: '/dist/', // 通过devServer访问路径
            filename: 'build.js' // 打包后的文件名
        },
        devServer: {
            historyApiFallback: true,
            overlay: true
        }
    };
    
    1. 启动之前, 我们需要修改一下package.json. 添加两条启动命令 package.json
      "scripts": {
        // webpack-dev-server会自动启动一个静态资源web服务器 --hot参数表示启动热更新
        "dev": "webpack-dev-server --open --hot",
        "build": "webpack --progress --hide-modules"
      },
    
    1. 这样执行npm run dev , 就可以初步启动项目了, 然后随意修改util.js, 可以发现浏览器会
      自动刷新, 很方便, 如果需要看打包后的bundle.js文件, 可以执行 npm run build,就可以在
      dist文件夹下看到生成的bundle.js.
  2. 引入vue

    1. 首先安装vue,
      npm i vue --save

    2.然后修改main.js文件和index.html文件, 以及webpack.config.js文件
    main.js

    import Vue from 'vue';
    
    var app = new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue!'
      }
    });
    

    index.html

    <!DOCTYPE html>
      <html lang="en">
    
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <meta http-equiv="X-UA-Compatible" content="ie=edge">
          <title>Document</title>
      </head>
    
      <body>
          <div id="app">
              {{message}}
          </div>
          <script src="/dist/build.js"></script>
          
      </body>
    
      </html>
    

    webpack.config.js

      var path = require('path');
      var webpack = require('webpack');
    
      module.exports = {
          entry: './src/main.js',
          output: {
              path: path.resolve(__dirname, './dist'),
              publicPath: '/dist/',
              filename: 'build.js'
          },
          devServer: {
              historyApiFallback: true,
              overlay: true
          },
          resolve: {
              alias: {
                // 添加识别路径
                  'vue$': 'vue/dist/vue.esm.js'
              }
          }
      };
    

    到这, 重新运行 npm run dev, 就可以了.

  3. 引入scss和css

    1. 安装相应的loader
      npm i node-sass css-loader vue-style-loader sass-loader --save-dev
    2. 修改 webpack.config.js
    var path = require('path');
    var webpack = require('webpack');
    
    module.exports = {
        entry: './src/main.js',
        output: {
            path: path.resolve(__dirname, './dist'),
            publicPath: '/dist/',
            filename: 'build.js'
        },
        devServer: {
            historyApiFallback: true,
            overlay: true
        },
        resolve: {
            alias: {
                'vue$': 'vue/dist/vue.esm.js'
            }
        },
        module: {
            rules: [
                {
                    test: /\.css$/, //匹配后缀名为css的文件
                    use: [ //分别用css-loader,vue-style-loader去解析
                    //  解析器的执行顺序是从下往上(先css-loader再vue-style-loader)
                    // 因为我们这里用vue开发,所以使用vue-style-loader,其他情况使用style-loader
                        'vue-style-loader',
                        'css-loader'
                    ],
                },
                // 下列同理
                {
                test: /\.scss$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'sass-loader'
                ],
                },
                {
                    test: /\.sass$/,
                    use: [
                        'vue-style-loader',
                        'css-loader',
                        'sass-loader?indentedSyntax'
                    ],
                }
            ]
        }
    };
    
    1. 在src目录下新建style文件夹, 新建common.scss,写个样式, 然后在main.js中引入 common.js
    body {
        background: #fed;
    }
    

    main.js
    import './style/common.scss';
    当然, 这里在引入文件的时候,我们可以像上述讲过的, 在webpack.config.js中的resolve里,配置一下
    文件引入的规则

    resolve: {
            alias: {
              // 添加识别路径
                'vue$': 'vue/dist/vue.esm.js',
                '@style': path.join(__dirname, './', 'src/style'),
            }
        }
    
    

    配置完成后, 就可以直接引入 @style/common.scss 这样也是能指向正确的文件的, 这个在项目中会比较实用

8.使用babel转码, 可以将ES6转码成ES5语法, 这样就可以在项目中使用最新特性了

  1. 安装
    npm i babel-core babel-loader babel-preset-env babel-preset-stage-3 --save-dev
    2.在项目根目录新建一个.babelrc文件, 写入内容, 然后在webpack.config.js中添加一个loader
    .babelrc

        {
      "presets": [
        ["env", { "modules": false }],
        "stage-3"
      ]
    }
    

    webpack.config.js

      .... 
      {
          test: /\.js$/,
          loader: 'babel-loader',
          // exclude表示忽略node_modules文件夹下的文件,不用转码
          exclude: /node_modules/
      }
    
    1. 安装babel-polyfill, 然后修改webpack.config.js的入口

    npm i babel-polyfill --save-dev
    修改 webpack.config.js

    entry: ['babel-polyfill', './src/main.js'],
    

    这样就可以测试async, await等es6的语法了.

  2. 引入图片, 文件, 等等就不细说了, 方式都一样.
    npm i file-loader --save-dev
    然后添加一个loader

{
  test: /\.(png|jpg|gif|svg)$/,
  loader: 'file-loader',
  options: {
      name: '[name].[ext]?[hash]'
  }
}
  1. devServer, 在日常开发过程中,经常需要与多人后端开发联调, 这个时候就需要代理某些URL
   module.exports = {
   //...
       devServer: {
           proxy: {
           '/api': {
               target: 'http://localhost:3000',
               pathRewrite: {'^/api' : ''}
           },
           '/bff': {
               target: 'http://localhost:3020',
               pathRewrite: {'^/bff' : ''}
           },

         }
       }
   };

这块就不细说了, 放个链接需要更多了解的可以点击查看 https://www.jianshu.com/p/f489e7764cb8

vue-单文件组件

1.安装vue-loader并添加vue-loader
npm i vue-loader vue-template-compiler --save-dev
webpack.config.js 添加一个loader

    {
      test: /\.vue$/,
      loader: 'vue-loader',
      options: {
          loaders: {
              'scss': [
                  'vue-style-loader',
                  'css-loader',
                  'sass-loader'
              ],
              'sass': [
                  'vue-style-loader',
                  'css-loader',
                  'sass-loader?indentedSyntax'
              ]
          }
      }
  }
  1. 在src目录下新建一个App.vue
<template>
  <div id="app">
    <h1>{{ msg }}</h1>
    <img src="./img/logo.png">
    <input type="text" v-model="msg">
  </div>
</template>

<script>

import getData from './util';

export default {
  name: 'app',
  data () {
    return {
      msg: 'Welcome to Your Vue.js'
    }
  },
  created() {
    this.fetchData();
  },
  methods: {
    async fetchData() {
      const data = await getData();
      this.msg = data;
    }
  }
}
</script>

<style lang="scss">
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;

  h1 {
    color: green;
  }
}
</style>

main.js

import Vue from 'vue';
import App from './App.vue';

import './style/common.scss';

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})

index.html

<!DOCTYPE html>
  <html lang="en">

  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
  </head>

  <body>
      <div id="app"></div>
      <script src="/dist/build.js"></script>
  </body>

  </html>

source-map

在开发阶段,调试也是非常重要的一项需求。 source-map构建了处理前的代码和处理后的代码之间的桥梁。主要是方便开发人员的错误定位。这里的处理操作包括: I)压缩,减小体积 II)将多个文件合并成同一个文件 III)其他语言编译成javascript,比如TypeScript和CoffeeScript等
修改webpack.config.js

module.exports = {
    entry: ['babel-polyfill', './src/main.js'],
    // 省略其他...

    devtool: '#eval-source-map'
}; 

打包发布

  1. 安装cross-env
    npm i cross-env --save-dev
  2. 修改package.json
"scripts": {
  "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
  "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}

修改webpack.config.js,判断NODE_ENV为production时,压缩js代码

var path = require('path');
var webpack = require('webpack');

module.exports = {
    // 省略...
}

if (process.env.NODE_ENV === 'production') {
    module.exports.devtool = '#source-map';
    module.exports.plugins = (module.exports.plugins || []).concat([
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: '"production"'
        }
      }),
      new webpack.optimize.UglifyJsPlugin(),
    ])
  }

结尾

这样, 一个基本的webpack+vue的项目就搭建好了, 其实类似的文章很多, 也有现成的脚手架来搭建, 这篇文章反倒是
一个基础性的文章, 没什么太大的技术点. 不过话说回来, 作为一个前端工程师, 怎么也得有一篇从零开始的基础文档
以供以后忘了参考嘛, 哈哈, 好了, 不说太多, 希望能对各位小伙伴有些帮助.
最后, 照例, 加油, 各位!