仿 vue-cli 搭建屬於本身的項目

前言

前段時間學習了webpack4的相關配置, webpack4入門篇,以前的全部項目都是使用vue-cli來搭建的,恰好公司最近有個新的項目要啓動,想提高本身的逼格,正好也能夠鞏固以前學習的webpack4的內容,決定本身用webpack來搭建一個屬於本身的腳手架。css

目錄結構

├── README.md
├── configs /全部的webpack配置
│   ├── util.js //webpack公用的方法工具庫
│   ├── webpack.base.conf.js //基礎配置
│   ├── webpack.dev.conf.js //開發配置
│   └── webpack.prod.conf.js //生產配置
├── dist //打包後的dist文件
│   ├── index.html
│   ├── logo.png
│   └── static
│       ├── css
│       │   └── 2.css
│       └── js
│           ├── 2.239af13846609eabe4c9.js
│           ├── main.4bd6023f63b0f953e5d2.js
│           └── vendor.1a84b3d307a7f4c10aad.js
├── .babelrc //babel文件配置
├── index.html //入口html文件
├── package-lock.json
├── package.json
├── src
│   ├── App.vue
│   ├── assets //css、img、js、vue組件
│   │   ├── css
│   │   ├── img
│   │   │   └── logo.png
│   │   └── js
│   ├── components
│   │   └── test.vue
│   ├── main.js //入口js文件
│   └── router //路由
│       └── index.js
└── webpack.config.js //真正使用的webpack文件	
複製代碼

詳細代碼

關於webpack的全部配置(主要部分)

###1. webpack.base.conf.jshtml

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const util = require('./util');

module.exports = {
  entry: {
    'main': './src/main.js'
  },
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].[hash:8].js',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        include: [path.resolve(__dirname, '../src')],
        use: [
          'vue-style-loader',
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../',//爲了防止css裏面有引用背景圖片 圖片打包以後在dist/images路徑錯誤問題
              hmr: devMode, // 僅dev環境啓用HMR功能
            }
          },
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: [require('autoprefixer')("last 100 versions")]
            }
          }
        ]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000, //是把小於10000B的文件打成Base64的格式,寫入JS
              name: util.assetsPath("images/[name]-[hash:5].[ext]"),
            }
          }
        ]
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: util.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.js$/,  //es6 => es5
        exclude: /node_modules/,
        use: 'babel-loader'
      },
      {
        test: /\.vue$/,
        use: 'vue-loader'
      },
      {
        test: /\.pug$/,
        oneOf: [
          // this applies to `<template lang="pug">` in Vue components
          {
            resourceQuery: /^\?vue/,
            use: ['pug-plain-loader']
          },
          // this applies to pug imports inside JavaScript
          {
            use: ['raw-loader', 'pug-plain-loader']
          }
        ]
      },

    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 配置輸出文件名和路徑
      template: './index.html', // 配置要被編譯的html文件
      favicon: './src/assets/img/logo.png', //logo
      hash: true, //是否生成hash添加在引入文件地址的末尾,這個能夠避免緩存帶來的麻煩
    }),
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: devMode ? util.assetsPath('css/[name].css') : util.assetsPath('css/[name].[hash].css'),
      chunkFilename: devMode ? util.assetsPath('css/[id].css') : util.assetsPath('css/[id].[hash].css'),
    }),
    new VueLoaderPlugin(),
  ],
  resolve: {
    extensions: ['.vue', '.js', '.json', '.css'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@':
        path.resolve(__dirname, '..', 'src'),
      '@components':
        path.resolve(__dirname, '..', 'src/components/'),
      '@assets':
        path.resolve(__dirname, '..', 'src/assets'),
    },
  }
};	
複製代碼

2. webpack.dev.conf.js

const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');

const devWebpackConfig = merge(baseWebpackConfig, {
  output:{
    publicPath: '/'
  },
  devtool: 'eval-source-map', // 指定加source-map的方式
  mode: 'development',
  devServer: {
    host: '0.0.0.0',//主機名
    port: 8080,//端口
    open: true,//自動打開瀏覽器
    compress: true,//服務器壓縮
    hot: true,//熱更新
    inline: true,//頁面自動刷新
    //跨域問題
    proxy: {
      '/api': {
        target: 'https://testbi.promni.cn/v2/api',
        secure: false,
        changeOrigin: true,
        pathRewrite: {'^/api': ''}
      }
    },
  }
});

module.exports = devWebpackConfig;
複製代碼

3. webpack.pro.conf.js

const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const util = require('./util');

const webpackConfig = merge(baseWebpackConfig, {
  output:{
    publicPath: './',
    filename: util.assetsPath('js/[name].[chunkhash].js')
  },
  optimization: {
    //壓縮文件 mode:production 生產環境配置
    minimizer: [
      new OptimizeCssAssetsWebpackPlugin(),// 壓縮css
      new UglifyJsPlugin()//壓縮js
    ],
    //提取公用代碼
    splitChunks: {
      cacheGroups: {
        commons: {
          // 抽離本身寫的公共代碼
          chunks: 'initial',
          name: 'common', // 打包後的文件名,任意命名
          minChunks: 2, //最小引用2次
          minSize: 0 // 只要超出0字節就生成一個新包
        },
        styles: {
          name: 'styles', // 抽離公用樣式
          test: /\.css$/,
          chunks: 'all',
          minChunks: 2,
          enforce: true
        },
        vendor: {
          // 抽離第三方插件
          test: /node_modules/, // 指定是node_modules下的第三方包
          chunks: 'initial',
          name: 'vendor', // 打包後的文件名,任意命名
          // 設置優先級,防止和自定義的公共代碼提取時被覆蓋,不進行打包
          priority: 10
        }
      }
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 配置輸出文件名和路徑
      template: './index.html', // 配置要被編譯的html文件
      favicon: './src/assets/img/logo.png', //logo
      hash: true, //是否生成hash添加在引入文件地址的末尾,這個能夠避免緩存帶來的麻煩
      minify: {
        removeAttributeQuotes: true, //去掉屬性引用 刪除雙引號
        collapseWhitespace: true, //是否去除空格 摺疊 html 爲一行
        removeComments: true//去註釋
      },
      chunksSortMode: 'dependency', //這個選項決定了 script 標籤的引用順序
    })
  ]
});

module.exports = webpackConfig;
複製代碼

4.util.js

'use strict';

//爲了讓打包以後的文件都在dist/static目錄下
const path = require('path');

exports.assetsPath = function (_path) {
  const assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? 'static'
    : 'static';

  return path.posix.join(assetsSubDirectory, _path)
};
複製代碼

5.webpack.config.js

module.exports = function (env, argv) {
  return argv.mode === 'production' ? 
  require('./configs/webpack.prod.conf') : 
  require('./configs/webpack.dev.conf');
};
複製代碼

package.json文件

{
  "name": "promni-xmc-web",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --mode development",
    "build": "webpack --mode production"
  },
  "repository": {
    "type": "git",
    "url": "https://code.promni.cn/lihaofeng/promni-xmc-web.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^9.6.4",
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-preset-env": "^1.7.0",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.2.0",
    "file-loader": "^4.2.0",
    "html-webpack-plugin": "^3.2.0",
    "mini-css-extract-plugin": "^0.8.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "path": "^0.12.7",
    "postcss-loader": "^3.0.0",
    "pug-plain-loader": "^1.0.0",
    "raw-loader": "^3.1.0",
    "style-loader": "^1.0.0",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "url-loader": "^2.2.0",
    "vue-loader": "^15.7.1",
    "vue-style-loader": "^4.1.2",
    "vue-template-compiler": "^2.6.10",
    "webpack": "^4.41.0",
    "webpack-cli": "^3.3.9",
    "webpack-dev-server": "^3.8.2",
    "webpack-merge": "^4.2.2"
  },
  "dependencies": {
    "pug": "^2.0.4",
    "vue": "^2.6.10",
    "vue-router": "^3.1.3"
  }
}
複製代碼

index.html文件

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>promni-xmc-web</title>
    <meta http-equiv=X-UA-Compatible content="chrome=1">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>	
複製代碼

.babelrc文件

{"presets": ["env"]}	
複製代碼

main.js入口文件

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

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  render: h => h(App)
});
複製代碼

App.vue文件

<template lang="pug">
    #app
        router-view
</template>

<script>
  export default {
    name: 'App'
  }
</script>
複製代碼

router裏面的index.js路由文件

import Vue from 'vue'
import Router from 'vue-router'

const test = r => require.ensure([], () => r(require('@components/test')));
Vue.use(Router);
const vueRouter = new Router({
  routes: [
    {
      path: '/',
      name: 'test',
      component: test
    }
  ]
});

export default vueRouter;
複製代碼

test.vue文件

<template lang="pug">
    div
        p 我是首頁
</template>
<style>
    p{
        color: red;
        background: url("../assets/img/logo.png") no-repeat;
    }
</style>	
複製代碼

總結

到這裏,最小可用的腳手架全部的文件源碼已經完成,接下來就能夠在compontents裏面使用vue愉快的寫咱們的業務代碼了。使用方式:先用npm i添加package.json裏面的依賴;開發環境使用npm run dev命令;生產環境使用npm run build命令打包。vue

相關文章
相關標籤/搜索