├── .browserslistrc ├── .env.development ├── .env.production ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── README.md ├── babel.config.js ├── config └── index.js ├── index.html ├── package-lock.json ├── package.json ├── public └── favicon.ico ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ └── HelloWorld.vue ├── main.js ├── router │ └── index.js ├── store │ └── index.js └── views │ ├── About.vue │ └── Home.vue ├── vite.config.js └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | VITE_APP_URL=https://jd.com/ 2 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | VITE_APP_URL=https://jd.com/ 2 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"], 7 | parserOptions: { 8 | parser: "babel-eslint" 9 | }, 10 | rules: { 11 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", 12 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off" 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # Log files 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | pnpm-debug.log* 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | *.sw? -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // trailingComma: "es5", 3 | // printWidth: 80, //一行的字符数,如果超过会进行换行,默认为80 4 | tabWidth: 2, //一个tab代表几个空格数,默认为80 5 | useTabs: false, //是否使用tab进行缩进,默认为false,表示用空格进行缩减 6 | singleQuote: true, //字符串是否使用单引号,默认为false,使用双引号 7 | semi: true, //行位是否使用分号,默认为true 8 | trailingComma: 'es5', //是否使用尾逗号,有三个可选值"" 9 | bracketSpacing: true, //对象大括号直接是否有空格,默认为true,效果:{ foo: bar } 10 | // "parser": "babylon" //代码的解析引擎,默认为babylon,与babel相同。 11 | htmlWhitespaceSensitivity: 'ignore', // html 处理标签异常问题 12 | arrowParens: 'avoid', 13 | }; 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vite-Vue2-demo 2 | 开发环境vite,webpack打包。 3 | 4 | - scss变量注入 5 | - alias 6 | - cdn引入,配置resolve externals 7 | - html模板语法 8 | 9 | ## Project setup 10 | ``` 11 | yarn install 12 | ``` 13 | 14 | ### Compiles and hot-reloads for development 15 | ``` 16 | # vite启动 17 | npm run dev 18 | ``` 19 | 20 | ### Compiles and minifies for production 21 | ``` 22 | yarn build 23 | ``` 24 | 25 | ### Lints and fixes files 26 | ``` 27 | yarn lint 28 | ``` 29 | 30 | ### Customize configuration 31 | See [Configuration Reference](https://cli.vuejs.org/config/). 32 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/cli-plugin-babel/preset"] 3 | }; 4 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | exports.genScssOptions = function(env) { 2 | let prependKey = env == 'vite' ? 'additionalData' : 'prependData'; 3 | return { 4 | [prependKey]: `$primary-color: #42b983;`, 5 | }; 6 | }; 7 | 8 | exports.genHtmlOptions = function(env) { 9 | const options = { 10 | title: 'Vite Vue2 Demo', 11 | }; 12 | if (env == 'vite') { 13 | process.env.TOOL_NAME = 'vite'; 14 | options.process = { 15 | // 注入env 16 | env: process.env, 17 | }; 18 | } 19 | return options; 20 | }; 21 | 22 | /** 23 | * 获取vite的env配置 24 | * @returns webpack DefinePlugin Object 25 | */ 26 | exports.getViteEnvVarDefine = function() { 27 | // 打包处理.env 28 | const dotenv = require('dotenv'); 29 | const dotenvExpand = require('dotenv-expand'); 30 | 31 | const envResult = dotenv.config(); 32 | const { parsed: envParsed } = dotenvExpand(envResult); 33 | 34 | const viteEnvDefine = {}; 35 | Object.keys(envParsed || {}).reduce((pre, cur) => { 36 | pre[`process.env.${cur}`] = JSON.stringify(envParsed[cur]); 37 | return pre; 38 | }, viteEnvDefine); 39 | 40 | return viteEnvDefine; 41 | }; 42 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= title %> 9 | 10 | 11 | 12 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | <% if (process.env.TOOL_NAME == 'vite') { %> 26 | 27 | <% } %> 28 | 29 | 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-vue2-demo", 3 | "version": "0.1.0", 4 | "private": false, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "core-js": "^3.6.5" 12 | }, 13 | "devDependencies": { 14 | "@vue/cli-plugin-babel": "^4.4.0", 15 | "@vue/cli-plugin-eslint": "^4.4.0", 16 | "@vue/cli-plugin-router": "^4.4.0", 17 | "@vue/cli-plugin-vuex": "^4.4.0", 18 | "@vue/cli-service": "^4.4.0", 19 | "@vue/eslint-config-prettier": "^6.0.0", 20 | "babel-eslint": "^10.1.0", 21 | "dotenv": "^8.2.0", 22 | "dotenv-expand": "^5.1.0", 23 | "eslint": "^6.7.2", 24 | "eslint-plugin-prettier": "^3.1.3", 25 | "eslint-plugin-vue": "^6.2.2", 26 | "prettier": "^1.19.1", 27 | "raw-edit-loader": "^0.2.0", 28 | "sass": "^1.32.8", 29 | "sass-loader": "^8.0.2", 30 | "vite": "^2.3.6", 31 | "vite-plugin-html": "^2.0.2", 32 | "vite-plugin-resolve-externals": "^0.1.0", 33 | "vite-plugin-vue2": "^1.2.1", 34 | "vue-template-compiler": "2.6.10" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lceric/vite-vue2-demo/2faaa43584439f1c3369e2c62af1d7940c5fb897/public/favicon.ico -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 11 | 20 | 42 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lceric/vite-vue2-demo/2faaa43584439f1c3369e2c62af1d7940c5fb897/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 104 | 105 | 113 | 114 | 115 | 131 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import router from './router'; 4 | import store from './store'; 5 | 6 | import ElementUI from 'element-ui'; 7 | 8 | Vue.use(ElementUI); 9 | import axios from 'axios'; 10 | Vue.prototype.$api = axios; 11 | Vue.config.productionTip = false; 12 | 13 | new Vue({ 14 | router, 15 | store, 16 | render: h => h(App), 17 | }).$mount('#app'); 18 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import VueRouter from "vue-router"; 3 | import Home from "../views/Home.vue"; 4 | 5 | Vue.use(VueRouter); 6 | 7 | const routes = [ 8 | { 9 | path: "/", 10 | name: "Home", 11 | component: Home 12 | }, 13 | { 14 | path: "/about", 15 | name: "About", 16 | // route level code-splitting 17 | // this generates a separate chunk (about.[hash].js) for this route 18 | // which is lazy-loaded when the route is visited. 19 | component: () => 20 | import(/* webpackChunkName: "about" */ "../views/About.vue") 21 | } 22 | ]; 23 | 24 | const router = new VueRouter({ 25 | routes 26 | }); 27 | 28 | export default router; 29 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Vuex from "vuex"; 3 | 4 | Vue.use(Vuex); 5 | 6 | export default new Vuex.Store({ 7 | state: {}, 8 | mutations: {}, 9 | actions: {}, 10 | modules: {} 11 | }); 12 | -------------------------------------------------------------------------------- /src/views/About.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { defineConfig } = require('vite'); 3 | const { createVuePlugin } = require('vite-plugin-vue2'); 4 | const { injectHtml } = require('vite-plugin-html'); 5 | const resolveExternalsPlugin = require('vite-plugin-resolve-externals'); 6 | 7 | const { genScssOptions, genHtmlOptions } = require('./config'); 8 | const projectRootDir = path.resolve(__dirname); 9 | 10 | // https://vitejs.dev/config/ 11 | export default defineConfig({ 12 | plugins: [ 13 | resolveExternalsPlugin({ 14 | vue: 'Vue', 15 | vuex: 'Vuex', 16 | 'vue-router': 'VueRouter', 17 | 'element-ui': 'ELEMENT', 18 | }), 19 | createVuePlugin({ 20 | jsx: true, 21 | }), 22 | injectHtml({ 23 | injectData: genHtmlOptions('vite'), 24 | }), 25 | ], 26 | css: { 27 | preprocessorOptions: { 28 | scss: genScssOptions('vite'), 29 | }, 30 | }, 31 | resolve: { 32 | alias: [ 33 | { 34 | find: '@', 35 | replacement: path.resolve(projectRootDir, 'src'), 36 | }, 37 | ], 38 | externals: { 39 | axios: 'axios', 40 | }, 41 | }, 42 | }); 43 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const { readFileSync, writeFileSync, existsSync, mkdirSync } = require('fs'); 2 | const path = require('path'); 3 | const webpack = require('webpack'); 4 | const { 5 | genScssOptions, 6 | genHtmlOptions, 7 | getViteEnvVarDefine, 8 | } = require('./config'); 9 | 10 | const indexPath = path.resolve(__dirname, './index.html'); 11 | const tmpDir = path.resolve(__dirname, 'node_modules/.tmp/build'); 12 | mkdirSyncRecursive(tmpDir); 13 | 14 | // vite import.meta.env => webpack process.env 15 | const rawEditLoaderOptions = () => ({ 16 | pathReg: 'src', 17 | replaceReg: 'import.meta.env.', 18 | replacement: 'process.env.', 19 | }); 20 | 21 | module.exports = { 22 | publicPath: './', 23 | // indexPath, 24 | css: { 25 | loaderOptions: { 26 | scss: genScssOptions(), 27 | }, 28 | }, 29 | chainWebpack: config => { 30 | config.externals({ 31 | axios: 'axios', 32 | vue: 'Vue', 33 | vuex: 'Vuex', 34 | 'vue-router': 'VueRouter', 35 | 'element-ui': 'ELEMENT', 36 | }); 37 | config 38 | .plugin('html') 39 | .tap(args => { 40 | const htmlOptions = genHtmlOptions(); 41 | const htmlStr = readFileSync(indexPath).toString(); 42 | const tmpHtmlPath = path.resolve(tmpDir, './index.html'); 43 | 44 | writeFileSync(tmpHtmlPath, htmlStr); 45 | 46 | args[0].template = tmpHtmlPath; 47 | args[0].title = htmlOptions.title; 48 | 49 | args[0].filename = './index.html'; 50 | args[0].templateParameters = ( 51 | compilation, 52 | assets, 53 | assetTags, 54 | options 55 | ) => { 56 | return { 57 | compilation, 58 | webpackConfig: compilation.options, 59 | htmlWebpackPlugin: { 60 | tags: assetTags, 61 | files: assets, 62 | options, 63 | }, 64 | ...htmlOptions, 65 | }; 66 | }; 67 | console.log(args); 68 | return args; 69 | }) 70 | .end(); 71 | }, 72 | configureWebpack: { 73 | module: { 74 | rules: [ 75 | { 76 | test: /\.js$/, 77 | use: [ 78 | { 79 | loader: 'raw-edit-loader', 80 | options: rawEditLoaderOptions(), 81 | }, 82 | ], 83 | }, 84 | ], 85 | }, 86 | plugins: [new webpack.DefinePlugin(getViteEnvVarDefine())], 87 | }, 88 | }; 89 | 90 | /** 91 | * 创建文件夹 92 | * @param {String} pathStr 文件夹路径 93 | */ 94 | function mkdirSyncRecursive(pathStr) { 95 | if (existsSync(pathStr)) return true; 96 | mkdirSync(pathStr, { 97 | recursive: true, 98 | }); 99 | } 100 | --------------------------------------------------------------------------------