Limengbo 5 роки тому
коміт
510fc30db7

+ 10 - 0
.babelrc

@@ -0,0 +1,10 @@
+{
+  "presets": [
+    ["env", {
+      "modules": false,
+      "targets": {
+        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
+      }
+    }]
+  ]
+}

+ 13 - 0
.editorconfig

@@ -0,0 +1,13 @@
+root = true
+
+# 对所有文件生效
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+# 对后缀名为 md 的文件生效
+[*.md]
+trim_trailing_whitespace = false

+ 5 - 0
.eslintignore

@@ -0,0 +1,5 @@
+build/*.js
+config/*.js
+src/assets
+/dist/
+/*.js

+ 31 - 0
.eslintrc.js

@@ -0,0 +1,31 @@
+module.exports = {
+  root: true, // 查找项
+  parserOptions: {
+    parser: 'babel-eslint'
+  },
+  env: {
+    browser: true,
+  },
+  extends: [
+    // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
+    // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
+    'plugin:vue/essential',
+    // https://github.com/standard/standard/blob/master/docs/RULES-en.md
+    'standard'
+  ],
+  // required to lint *.vue files
+  plugins: [
+    'vue'
+  ],
+  // add your custom rules here
+  rules: {
+    // allow async-await
+    'generator-star-spacing': 'off',
+    // allow debugger during development
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
+    // 缩进风格
+    'indent': ['error', 2],
+    // 空行不超过两行
+    'no-multiple-empty-lines': [1, {'max': 2}]
+  }
+}

+ 17 - 0
.gitignore

@@ -0,0 +1,17 @@
+.DS_Store
+node_modules/
+/dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+/test/unit/coverage/
+/test/e2e/reports/
+selenium-debug.log
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln

+ 36 - 0
README.md

@@ -0,0 +1,36 @@
+# webpack前端项目搭建
+
+## 目录结构
+
+```
+webpack-vue
+│   README.md //项目说明
+│   postcss.config.js //css前缀 
+│   package.json //依赖包
+|   index.html //页面
+|   .gitignore //git不提交的文件
+|   .eslintrc.js //eslint配置,规范代码
+|   .eslintignore //eslint不检测的文件 
+|   .editorconfig //编辑器配置
+|   .babelrc //babel配置
+|
+└───src 
+│   │   
+│   │   
+│   │
+│   └───
+│       │   
+│       │   
+│       │   
+│   
+└───config //生产环境和开发环境配置
+|   │   dev.env.js //开发环境
+|   │   prod.env.js //生产环境
+|
+└───build // webpack配置
+    | webpack.base.conf.js //全局配置
+    | webpack.dev.conf.js //开发环境配置
+    | webpack.prod.conf.js //生产环境配置
+```
+
+代码里都有注释,跟vue-cli构建项目差不多,参考[webpack](https://www.webpackjs.com/concepts/)

+ 86 - 0
build/webpack.base.conf.js

@@ -0,0 +1,86 @@
+// 存放dev和prod配置
+const path = require('path');
+const webpack = require('webpack');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const VueLoaderPlugin = require('vue-loader/lib/plugin');
+// 第三方库单独打包
+const AutoDllPlugin = require('autodll-webpack-plugin');
+// 分离css,打包到单独文件
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+
+module.exports = {
+  entry: {
+    bundle: path.resolve(__dirname, '../src/main.js')
+  },
+  output: {
+    path: path.resolve(__dirname, '../dist'),
+    filename: '[name].[hash].js'
+  },
+  module: {
+    rules: [
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader'
+      },
+      {
+        test: /\.js$/,
+        use: ['babel-loader'],
+        include: path.resolve(__dirname + '/src/'),
+        exclude: /node_modules/
+      },
+      {
+        test: /\.(png|svg|jpg|gif)$/,
+        use: [
+          'file-loader'
+        ]
+      },
+      {
+        test: /\.(woff|woff2|eot|ttf|otf)$/,
+        use: [
+          'file-loader'
+        ]
+      },
+      {
+        test: /\.less$/,
+        use: [
+          {
+            loader: MiniCssExtractPlugin.loader,
+            options: {
+              publicPath: '../'
+            }
+          },
+          'css-loader',
+          'postcss-loader',
+          'less-loader',
+        ],
+      },
+    ]
+  },
+  plugins: [
+    new webpack.HashedModuleIdsPlugin(), // 解决vender后面的hash每次都改变
+    new HtmlWebpackPlugin({
+      template: path.resolve(__dirname, '../index.html')
+    }),
+    new AutoDllPlugin({
+      inject: true, // will inject the DLL bundle to index.html
+      debug: true,
+      filename: '[name]_[hash].js',
+      path: './dll',
+      entry: {
+        vendor: ['vue', 'vue-router', 'vuex']
+      }
+    }), //单独打包第三方库
+    new VueLoaderPlugin(), // 它的职责是将你定义过的其它规则复制并应用到 .vue 文件里相应语言的块
+    new webpack.optimize.SplitChunksPlugin() // 提取公共代码
+  ],
+  resolve: {
+    extensions: ['.js', '.scss', '.css', '.vue'],// 省去后缀
+    alias: {
+        'vue$': 'vue/dist/vue.esm.js', //配置别名 确保webpack可以找到.vue文件
+        "@": path.resolve(__dirname, '../src'),
+        "components": path.resolve(__dirname, '../src/components'),
+        "utils": path.resolve(__dirname + '../src/utils')
+    },
+    modules: ['node_modules']
+  }
+}

+ 33 - 0
build/webpack.dev.conf.js

@@ -0,0 +1,33 @@
+// 存放dev配置
+const merge = require('webpack-merge');
+const webpack = require('webpack');
+const baseConfig = require('./webpack.base.conf');
+const path = require('path');
+
+module.exports = merge(baseConfig, {
+  mode: 'development',
+  devtool: 'inline-source-map',
+  module: {
+    rules: [
+      {
+        test: /\.css$/,
+        use: [
+          'vue-style-loader',
+          'css-loader', 
+          'postcss-loader'
+        ]
+      }
+    ]
+  },
+  devServer: {
+    contentBase: path.resolve(__dirname, '../dist'), //告诉服务其从哪提供内容
+    hot: true,
+    open: true
+  },
+  plugins: [
+    new webpack.HotModuleReplacementPlugin(), // 开启热更新
+    new webpack.DefinePlugin({
+      'process.env': require('../config/dev.env')
+    }), // 配置请求地址
+  ]
+})

+ 38 - 0
build/webpack.prod.conf.js

@@ -0,0 +1,38 @@
+// 存放prod配置
+const merge = require('webpack-merge');
+const baseConfig = require('./webpack.base.conf');
+const path = require('path');
+const webpack = require('webpack');
+// 清除打包多余文件
+const CleanWebpackPlugin = require('clean-webpack-plugin');
+// 分离css,打包到单独文件
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+// 压缩css
+const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
+
+module.exports = merge(baseConfig, {
+  mode: 'production',
+  devtool: 'source-map',
+  module: {
+    rules: [
+      {
+        test: /\.css$/,
+        use: [
+          MiniCssExtractPlugin.loader,
+          'css-loader', 
+          'postcss-loader'
+        ]
+      }
+    ]
+  },
+  plugins: [
+    new CleanWebpackPlugin(),
+    new MiniCssExtractPlugin({
+      filename: "css/[name].css",
+      chunkFilename: "css/[id].css"
+    }),
+    new webpack.DefinePlugin({
+      'process.env': require('../config/prod.env')
+    }), // 配置请求地址
+  ]
+})

+ 8 - 0
config/dev.env.js

@@ -0,0 +1,8 @@
+'use strict'
+const merge = require('webpack-merge')
+const prodEnv = require('./prod.env')
+
+module.exports = merge(prodEnv, {
+  NODE_ENV: '"development"',
+  BASE_API: '"https://123456789"',
+})

+ 5 - 0
config/prod.env.js

@@ -0,0 +1,5 @@
+'use strict'
+module.exports = {
+  NODE_ENV: '"production"',
+  BASE_API: '"https://11111"',
+}

+ 12 - 0
index.html

@@ -0,0 +1,12 @@
+<!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>webpack构建vue</title>
+</head>
+<body>
+  <div id="app"></div>
+</body>
+</html>

Різницю між файлами не показано, бо вона завелика
+ 8682 - 0
package-lock.json


+ 44 - 0
package.json

@@ -0,0 +1,44 @@
+{
+  "name": "webpack-vue",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+    "build": "webpack --config build/webpack.prod.conf.js",
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
+  "devDependencies": {
+    "autodll-webpack-plugin": "^0.4.2",
+    "autoprefixer": "^9.5.1",
+    "babel-core": "^6.26.3",
+    "babel-eslint": "^10.0.1",
+    "babel-loader": "^7.1.5",
+    "babel-preset-env": "^1.7.0",
+    "clean-webpack-plugin": "^2.0.1",
+    "css-loader": "^2.1.1",
+    "eslint-plugin-vue": "^5.2.2",
+    "file-loader": "^3.0.1",
+    "html-webpack-plugin": "^3.2.0",
+    "less-loader": "^4.1.0",
+    "mini-css-extract-plugin": "^0.5.0",
+    "optimize-css-assets-webpack-plugin": "^5.0.1",
+    "postcss-loader": "^3.0.0",
+    "uglifyjs-webpack-plugin": "^2.1.2",
+    "vue": "^2.6.10",
+    "vue-loader": "^15.7.0",
+    "vue-style-loader": "^4.1.2",
+    "vue-template-compiler": "^2.6.10",
+    "webpack": "^4.29.6",
+    "webpack-cli": "^3.3.0",
+    "webpack-dev-server": "^3.3.0",
+    "webpack-merge": "^4.2.1"
+  },
+  "dependencies": {
+    "vue-router": "^3.0.3",
+    "vuex": "^3.1.0"
+  }
+}

+ 5 - 0
postcss.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  plugins: [
+    require('autoprefixer')
+  ]
+}

+ 19 - 0
src/App.vue

@@ -0,0 +1,19 @@
+<template>
+  <div id="app">
+    <router-view/>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'App',
+    data(){
+      return {
+
+      }
+    }
+  }
+</script>
+
+<style>
+</style>

+ 41 - 0
src/components/tab.vue

@@ -0,0 +1,41 @@
+<style scoped>
+  .tab {
+    width: 5rem;
+    height: 1.5rem;
+    background-color: cornflowerblue;
+    position: relative;
+  }
+  .tab::before {
+    content: "";
+    height: 0;
+    width: 0;
+    border: 0.75rem solid cornflowerblue;
+    border-top-color: transparent;
+    border-left-color: transparent;
+    position: absolute;
+    left: -1.5rem;
+    bottom: 0;
+  }
+  .tab::after {
+    content: "";
+    height: 0;
+    width: 0;
+    border: 0.75rem solid cornflowerblue;
+    border-top-color: transparent;
+    border-right-color: transparent;
+    position: absolute;
+    left: 100%;
+    bottom: 0;
+  }
+</style>
+
+<template>
+  <div class="tab">
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'tab'
+}
+</script>

+ 11 - 0
src/index.css

@@ -0,0 +1,11 @@
+html, body {
+  width: 100%;
+  height: 100%;
+  font-size: 16px;
+  padding: 0;
+  margin: 0
+}
+#app {
+  width: 100%;
+  height: 100%;
+}

+ 13 - 0
src/main.js

@@ -0,0 +1,13 @@
+import Vue from 'vue';
+import App from './App.vue';
+import './index.css';
+import router from './router/router'
+import store from './store'
+ new Vue({
+    el: '#app',
+    router,
+    store,
+    render: (h) => h(App),
+ })
+
+console.log(process.env.BASE_API)

+ 15 - 0
src/router/router.js

@@ -0,0 +1,15 @@
+import Vue from 'vue';
+import Router from 'vue-router';
+import tab from 'components/tab'
+
+Vue.use(Router)
+
+export default new Router({
+  mode: 'history',
+  // base: process.env.BASE_URL,
+  routes: [{
+    path: '/',
+    name:'home',
+    component: tab
+  }]
+})

+ 4 - 0
src/store/getter.js

@@ -0,0 +1,4 @@
+const getters = {
+  device: state => state.app.device
+}
+export default getters

+ 15 - 0
src/store/index.js

@@ -0,0 +1,15 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import app from './modules/app'
+import getters from './getter'
+
+Vue.use(Vuex)
+
+const store = new Vuex.Store({
+  modules: {
+    app
+  },
+  getters
+})
+
+export default store

+ 18 - 0
src/store/modules/app.js

@@ -0,0 +1,18 @@
+
+const app = {
+  state: {
+    device: 'desktop'
+  },
+  mutations: {
+    TOGGLE_DEVICE: (state, device) => {
+      state.device = device
+    }
+  },
+  actions: {
+    ToggleDevice({ commit }, device) {
+      commit('TOGGLE_DEVICE', device)
+    }
+  }
+}
+
+export default app