面试官:自己搭建过vue开发环境吗?

栏目: CSS · 发布时间: 5年前

内容简介:前段时间,看到群里一些小伙伴面试的时候被面试官问到这类题目。平时大家开发vue项目的时候,相信大部分人都是使用但是对项目里的该篇文章主要是想告诉小伙伴们,如何一步一步的通过

前段时间,看到群里一些小伙伴面试的时候被面试官问到这类题目。平时大家开发vue项目的时候,相信大部分人都是使用 vue-cli 脚手架生成的项目架构,然后 npm run install 安装依赖, npm run serve 启动项目然后就开始写业务代码了。

但是对项目里的 webpack 封装和配置了解的不清楚,容易导致出问题不知如何解决,或者不会通过 webpack 去扩展新功能。

该篇文章主要是想告诉小伙伴们,如何一步一步的通过 webpack4 来搭建自己的 vue 开发环境

首先我们要知道 vue-cli 生成的项目,帮我们配置好了哪些功能?

  1. ES6 代码转换成 ES5 代码
  2. scss/sass/less/styluscss
  3. .vue 文件转换成 js 文件
  4. 使用 jpgpngfont 等资源文件
  5. 自动添加css各浏览器产商的前缀
  6. 代码热更新
  7. 资源预加载
  8. 每次构建代码清除之前生成的代码
  9. 定义环境变量
  10. 区分开发环境打包跟生产环境打包
  11. ....
面试官:自己搭建过vue开发环境吗?

1. 搭建 webpack 基本环境

该篇文章并不会细讲 webpack 是什么东西,如果还不是很清楚的话,可以先去看看webpack官网

简单的说, webpack 是一个模块打包机,可以分析你的项目依赖的模块以及一些浏览器不能直接运行的语言 jsxvue 等转换成 jscss 文件等,供浏览器使用。

面试官:自己搭建过vue开发环境吗?

1.1 初始化项目

在命令行中执行 npm init 然后一路回车就行了,主要是生成一些项目基本信息。最后会生成一个 package.json 文件

npm init
复制代码

1.2 安装 webpack

面试官:自己搭建过vue开发环境吗?

1.3 写点小代码测试一下 webpack 是否安装成功了

新建一个 src 文件夹,然后再建一个 main.js 文件

// src/main.js
console.log('hello webpack')
复制代码

然后在 package.json 下面加一个脚本命令

面试官:自己搭建过vue开发环境吗?

然后运行该命令

npm run serve
复制代码

如果在 dist 目录下生成了一个 mian.js 文件,则表示 webpack 工作正常

2. 开始配置功能

  • 新建一个 build 文件夹,用来存放 webpack 配置相关的文件
  • build 文件夹下新建一个 webpack.config.js ,配置 webpack 的基本配置
  • 修改 webpack.config.js 配置
面试官:自己搭建过vue开发环境吗?
  • 修改 package.json 文件,将之前添加的 serve 修改为
"serve": "webpack ./src/main.js --config ./build/webpack.config.js"
复制代码

2.1 配置 ES6/7/8ES5 代码

  • 安装相关依赖
npm install babel-loader @babel/core @babel/preset-env
复制代码
  • 修改 webpack.config.js 配置
面试官:自己搭建过vue开发环境吗?
  • 在项目根目录添加一个 babel.config.js 文件
面试官:自己搭建过vue开发环境吗?
  • 然后执行 npm run serve 命令,可以看到 ES6代码被转成了ES5代码了

2.2 配置 scsscss

在没配置 css 相关的 loader 时,引入 scsscss 相关文件打包的话,会报错

  • 安装相关依赖
npm install sass-loader dart-sass css-loader style-loader -D
复制代码

sass-loader , dart-sass 主要是将 scss/sass 语法转为css

css-loader 主要是解析 css 文件

style-loader 主要是将 css 解析到 html 页面 的 style

  • 修改 webpack.config.js 配置
面试官:自己搭建过vue开发环境吗?

2.3 配置 postcss 实现自动添加css3前缀

  • 安装相关依赖
npm install postcss-loader autoprefixer -D
复制代码
  • 修改 webpack.config.js 配置
面试官:自己搭建过vue开发环境吗?
  • 在项目根目录下新建一个 postcss.config.js
面试官:自己搭建过vue开发环境吗?

2.3 使用 html-webpack-plugin 来创建html页面

使用 html-webpack-plugin 来创建html页面,并自动引入打包生成的 js 文件

  • 安装依赖
npm install html-webpack-plugin -D
复制代码
  • 新建一个 public/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>
</body>
</html>
复制代码
  • 修改 webpack-config.js 配置
    面试官:自己搭建过vue开发环境吗?

2.4 配置 devServer 热更新功能

通过代码的热更新功能,我们可以实现不刷新页面的情况下,更新我们的页面

  • 安装依赖
npm install webpack-dev-server -D
复制代码
  • 修改 webpack.config.js 配置

通过配置 devServerHotModuleReplacementPlugin 插件来实现热更新

面试官:自己搭建过vue开发环境吗?

2.5 配置 webpack 打包 图片、媒体、字体等文件

  • 安装依赖
npm install file-loader url-loader -D
复制代码

file-loader 解析文件url,并将文件复制到输出的目录中

url-loader 功能与 file-loader 类似,如果文件小于限制的大小。则会返回 base64 编码,否则使用 file-loader 将文件复制到输出的目录中

  • 修改 webpack-config.js 配置 添加 rules 配置,分别对 图片,媒体,字体文件进行配置
// build/webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
module.exports = {
  // 省略其它配置 ...
  module: {
    rules: [
      // ...
      {
        test: /\.(jpe?g|png|gif)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                    name: 'img/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'media/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'fonts/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
    ]
  },
  plugins: [
    // ...
  ]
}
复制代码

3. 让 webpack 识别 .vue 文件

  • 安装需要的依赖文件
npm install vue-loader vue-template-compiler cache-loader -D
npm install vue -S
复制代码
  • 修改 webpack.config.js 配置
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  // 指定打包模式
  mode: 'development',
  entry: {
    // ...
  },
  output: {
    // ...
  },
  devServer: {
    // ...
  },
  resolve: {
    alias: {
      vue$: 'vue/dist/vue.runtime.esm.js'
    },
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'vue-loader',
            options: {
              compilerOptions: {
                preserveWhitespace: false
              },
            }
          }
        ]
      },
      // ...
    ]
  },
  plugins: [
    // ...
    new VueLoaderPlugin()
  ]
}
复制代码
  • 测试一下
  1. 在 src 新建一个 App.vue
// src/App.vue
<template>
  <div class="App">
    Hello World
  </div>
</template>

<script>
export default {
  name: 'App',

  data() {
    return {};
  }
};
</script>

<style lang="scss" scoped>
@import './assets/styles/var.scss';
.App {
  color: $primary-color;
}
</style>
复制代码
  1. 修改 main.js
import Vue from 'vue'
import App from './App.vue'

new Vue({
  render: h => h(App)
}).$mount('#app')
复制代码
  1. 运行一下

npm run serve

4. 定义环境变量

通过 webpack 提供的 DefinePlugin 插件,可以很方便的定义环境变量

plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        VUE_APP_BASE_URL: JSON.stringify('http://localhost:3000')
      }
    }),
]
复制代码

5. 区分生产环境和开发环境

新建两个文件

  • webpack.dev.js 开发环境使用

  • webpack.prod.js 生产环境使用

  • webpack.config.js 公用配置

  • 开发环境与生产环境的不同

5.1 开发环境

  1. 不需要压缩代码
  2. 需要热更新
  3. css不需要提取到css文件
  4. sourceMap
  5. ...

5.2 生产环境

  1. 压缩代码
  2. 不需要热更新
  3. 提取css,压缩css文件
  4. sourceMap
  5. 构建前清除上一次构建的内容
  6. ...
  • 安装所需依赖
npm i @intervolga/optimize-cssnano-plugin mini-css-extract-plugin clean-webpack-plugin webpack-merge copy-webpack-plugin -D
复制代码
  1. @intervolga/optimize-cssnano-plugin 用于压缩css代码
  2. mini-css-extract-plugin 用于提取css到文件中
  3. clean-webpack-plugin 用于删除上次构建的文件
  4. webpack-merge 合并 webpack 配置
  5. copy-webpack-plugin 用户拷贝静态资源

5.3 开发环境配置

  • build/webpack.dev.js
// build/webpack.dev.js
const merge = require('webpack-merge')
const webpackConfig = require('./webpack.config')
const webpack = require('webpack')
module.exports = merge(webpackConfig, {
  mode: 'development',
  devtool: 'cheap-module-eval-source-map',
  module: {
    rules: [
      {
        test: /\.(scss|sass)$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2
            }
          },
          {
            loader: 'sass-loader',
            options: {
              implementation: require('dart-sass')
            }
          },
          {
            loader: 'postcss-loader'
          }
        ]
      },
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('development')
      }
    }),
  ]
})
复制代码
  • webpack.config.js
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  entry: {
    // 配置入口文件
    main: path.resolve(__dirname, '../src/main.js')
  },
  output: {
    // 配置打包文件输出的目录
    path: path.resolve(__dirname, '../dist'),
    // 生成的 js 文件名称
    filename: 'js/[name].[hash:8].js',
    // 生成的 chunk 名称
    chunkFilename: 'js/[name].[hash:8].js',
    // 资源引用的路径
    publicPath: '/'
  },
  devServer: {
    hot: true,
    port: 3000,
    contentBase: './dist'
  },
  resolve: {
    alias: {
      vue$: 'vue/dist/vue.runtime.esm.js'
    },
    extensions: [
      '.js',
      '.vue'
    ]
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'vue-loader',
            options: {
              compilerOptions: {
                preserveWhitespace: false
              },
            }
          }
        ]
      },
      {
        test: /\.jsx?$/,
        loader: 'babel-loader'
      },

      {
        test: /\.(jpe?g|png|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'img/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'media/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'fonts/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
    ]
  },
  plugins: [
    new VueLoaderPlugin(),

    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../public/index.html')
    }),
    new webpack.NamedModulesPlugin(),
    new webpack.HotModuleReplacementPlugin(),
  ]
}
复制代码

5.4 生产环境配置

const path = require('path')
const merge = require('webpack-merge')
const webpack = require('webpack')
const webpackConfig = require('./webpack.config')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssnanoPlugin = require('@intervolga/optimize-cssnano-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = merge(webpackConfig, {
  mode: 'production',
  devtool: '#source-map',
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          name: 'chunk-vendors',
          test: /[\\\/]node_modules[\\\/]/,
          priority: -10,
          chunks: 'initial'
        },
        common: {
          name: 'chunk-common',
          minChunks: 2,
          priority: -20,
          chunks: 'initial',
          reuseExistingChunk: true
        }
      }
    }
  },
  module: {
    rules: [
      {
        test: /\.(scss|sass)$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2
            }
          },
          {
            loader: 'sass-loader',
            options: {
              implementation: require('dart-sass')
            }
          },
          {
            loader: 'postcss-loader'
          }
        ]
      },
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: 'production'
      }
    }),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash:8].css',
      chunkFilename: 'css/[name].[contenthash:8].css'
    }),
    new OptimizeCssnanoPlugin({
      sourceMap: true,
      cssnanoOptions: {
        preset: [
          'default',
          {
            mergeLonghand: false,
            cssDeclarationSorter: false
          }
        ]
      }
    }),
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../public'),
        to: path.resolve(__dirname, '../dist')
      }
    ]),
    new CleanWebpackPlugin()
  ]
})

复制代码

5.5 修改package.json

"scripts": {
    "serve": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
},
复制代码

6 总结

到目前为止,我们已经成功的自己搭建了一个 vue 开发环境,不过还是有一些功能欠缺的,有兴趣的小伙伴可以交流交流。在搭建过程中,还是会踩很多坑的。

如果还不熟悉 webpack 的话,建议自己搭建一次。可以让自己能深入的理解 vue-cli 替我们做了什么

面试官:自己搭建过vue开发环境吗?

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Transcending CSS

Transcending CSS

Andy Clarke、Molly E. Holzschlag / New Riders / November 15, 2006 / $49.99

As the Web evolves to incorporate new standards and the latest browsers offer new possibilities for creative design, the art of creating Web sites is also changing. Few Web designers are experienced p......一起来看看 《Transcending CSS》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具