Интервьюер: Вы когда-нибудь сами создавали среду разработки Vue?

Vue.js
Интервьюер: Вы когда-нибудь сами создавали среду разработки Vue?

открытие

Оригинальный адрес:Woohoo.C code.live/Len too/list…

Код проекта:GitHub.com/Len too/vUE-…

Некоторое время назад я видел, как некоторые друзья в группе задавали такие вопросы интервьюеру, когда они брали интервью. Обычно, когда все разрабатывают vue-проект, я считаю, что большинство людей его используют.vue-cliПодготовьте сгенерированную схему проекта, затемnpm run installустановить зависимости,npm run serveЗапустите проект и начните писать бизнес-код.

Но для проектаwebpackНеясное понимание инкапсуляции и настройки может легко привести к проблемам и не знать, как их решить, или не пройтиwebpackдля расширения новой функциональности.

Эта статья в основном хочет рассказать моим друзьям, как пройти шаг за шагомwebpack4построить свой собственныйvueсреда разработки

Сначала нам нужно знатьvue-cliКакие функции нам помог настроить сгенерированный проект?

  1. ES6код вES5код
  2. scss/sass/less/stylusПеременаcss
  3. .vueфайл преобразован вjsдокумент
  4. использоватьjpg,png,fontи другие файлы ресурсов
  5. Автоматически добавлять префиксы производителей css браузеров
  6. Горячее обновление кода
  7. Предварительная загрузка ресурсов
  8. Каждый код сборки очищает ранее сгенерированный код
  9. определить переменные среды
  10. Различие между упаковкой среды разработки и упаковкой рабочей среды
  11. ....

1. Построитьwebpackосновная среда

В этой статье нет подробностейwebpackЧто-то, если не очень понятно, можно сначала съездить посмотреть.официальный сайт вебпака

Проще говоря,webpackЭто упаковщик модулей, который может анализировать модули, от которых зависит ваш проект, и некоторые языки, которые браузеры не могут запускать напрямую.jsx,vueи т. д., чтобы преобразовать вjs,cssфайлы и т. д. для использования браузером.

1.1 Инициализировать проект

выполнить в командной строкеnpm initЗатем просто нажмите Enter до упора, в основном для получения базовой информации о проекте. в конечном итоге сгенерируетpackage.jsonдокумент

npm init

1.2 Установкаwebpack

1.3 Напишите небольшой код для проверкиwebpackБыла ли установка успешной

создать новыйsrcпапку, а затем создайте другуюmain.jsдокумент

// src/main.js
console.log('hello webpack')

Затем добавьте команду скрипта ниже package.json

затем запустите команду

npm run serve

Если создан каталог distmain.jsфайл, значитwebpackработает отлично

2. Запустите функцию настройки

  • создать новыйbuildпапка для храненияwebpackФайлы, связанные с конфигурацией
  • существуетbuildсоздать новую папкуwebpack.config.js, настроитьwebpackбазовая конфигурация
  • Исправлятьwebpack.config.jsнастроить

  • Исправлятьpackage.jsonфайл, ранее добавленныйserveпревратиться в
"serve": "webpack ./src/main.js --config ./build/webpack.config.js"

2.1 КонфигурацияES6/7/8ПеременаES5код

  • Установить связанные зависимости
npm install babel-loader @babel/core @babel/preset-env
  • Исправлятьwebpack.config.jsнастроить

  • Добавьте один в корневой каталог проектаbabel.config.jsдокумент

  • затем выполнитьnpm run serveкоманда, вы можете видеть, что код ES6 был преобразован в код ES5

2.1.1 ES6/7/8 ApiПеременаes5

babel-loaderПреобразует только синтаксис ES6/7/8 в синтаксис ES5, но не для новых API.

Мы можем предоставить реализацию нового синтаксиса некоторым клиентам, которые не поддерживают новый синтаксис через babel-polyfill.

  • Установить
npm install @babel/polyfill
  • Исправлятьwebpack.config.jsнастроить

существуетentryдобавлено в@babel-polyfill

2.1.2 Внедрение по запросуpolyfill

2.1.2 и 2.1.1 нужно настроить только один

Изменено 2019-05-05, из области комментариевпо всему небунапоминание

  • Установить связанные зависимости
npm install core-js@2 @babel/runtime-corejs2 -S
  • Изменить babel-config.js

Настроен на импорт по запросуpolyfillПосле этого используйтеes6вышеуказанная функция,babelбудет автоматически импортировать связанныеpolyfill, что может сильно уменьшить объем после упаковки и компиляции

2.2 КонфигурацияscssПеременаcss

не настроеноcssСвязанныйloaderпри импортеscss,cssЕсли связанные файлы упакованы, будет сообщено об ошибке

  • Установить связанные зависимости
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настроить

2.3 Настройка реализации PostCSS для автоматического добавления префикса CSS3

  • Установить связанные зависимости
npm install postcss-loader autoprefixer -D
  • Исправлятьwebpack.config.jsнастроить

  • Создайте новый в корневом каталоге проектаpostcss.config.js

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настроить

2.4 Настройка функции горячего обновления devServer

Благодаря функции горячего обновления кода мы можем обновить нашу страницу, не обновляя страницу.

  • Установить зависимости
npm install webpack-dev-server -D
  • Исправлятьwebpack.config.jsнастроить

по конфигурацииdevServerа такжеHotModuleReplacementPluginПлагин для реализации горячего обновления

2.5 Настройте веб-пакет для упаковки изображений, мультимедиа, шрифтов и других файлов

  • Установить зависимости
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 thread-loader -D
npm install vue -S

vue-loaderдля разбора.vueдокумент

vue-template-compilerдля составления шаблонов

cache-loaderКэшloaderСкомпилированный результат

thread-loaderиспользоватьworkerбассейн для запускаloader, каждыйworkerвсе одноnode.jsобработать.

  • Исправлять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: 'thread-loader'
          },
          {
            loader: 'vue-loader',
            options: {
              compilerOptions: {
                preserveWhitespace: false
              },
            }
          }
        ]
      },
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'thread-loader'
          },
          {
            loader: 'babel-loader'
          }
        ]
      },
      // ...
    ]
  },
  plugins: [
    // ...
    new VueLoaderPlugin()
  ]
}
  • пройти тест
  1. Создайте новый App.vue в src
// src/App.vue
<template>
  <div class="App">
    Hello World
  </div>
</template>

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

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

<style lang="scss" scoped>
.App {
  color: skyblue;
}
</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');
/*   clean-webpack-plugin 3.0 以上的版本需要使用对象结构  */
// const CleanWebpackPlugin = require('clean-webpack-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 Анализ упаковки

Иногда нам нужно посмотреть, что упаковано после того, как упакован webpack.

В настоящее время вам необходимо использовать этот инструмент анализа модуля.webpack-bundle-analyzer

  • Установить зависимости
npm install --save-dev webpack-bundle-analyzer
  • Исправлятьwebpack-prod.jsконфигурация, вpluginsДобавить плагин в свойства

В среде разработки нам не нужно выполнять анализ упаковки модулей, поэтому настраиваем плагин в элементах конфигурации производственной среды

  • Запустите команду пакета
npm run build

После успешного выполнения эта страница будет открыта автоматически

7. ИнтеграцияVueRouter,Vuex

  1. Во-первых, установить соответствующие зависимости
npm install vue-router vuex --save

7.1 ИнтеграцияVue-Router

  • Добавить компонент представления существуетsrcДобавьте два новых компонента представления в каталогsrc/views/Home.vueа такжеsrc/views/About.vue
// src/views/Home.vue
<template>
  <div class="Home">
    <h2>Home</h2>
  </div>
</template>

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

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

<style lang="scss" scoped>
</style>

About.vueдовольствоватьсяHome.vueПочти, положить внутрьHomeзаменитьAboutНичего страшного

  • Добавить файл конфигурации маршрутизации

существуетsrcДобавить новый в каталогrouter/index.jsдокумент

// src/router/index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Home from '../views/Home';
import About from '../views/About';
Vue.use(VueRouter)
export default new VueRouter({
  mode: 'hash',
  routes: [
    {
      path: '/Home',
      component: Home
    },
    {
      path: '/About',
      component: About
    },
    {
      path: '*',
      redirect: '/Home'
    }
  ]
})
  • Исправлятьmain.jsдокумент
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
  • ИсправлятьApp.vueкомпоненты
// App.vue
// 在 template 中添加
// src/App.vue
<template>
  <div class="App">
    Hello World
  </div>
  <div>
      // router-link 组件 用来导航到哪个路由
      <router-link to="/Home">go Home</router-link>
      <router-link to="/About">go About</router-link>
    </div>
    <div>
      // 用于展示匹配到的路由视图组件
      <router-view></router-view>
    </div>
</template>

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

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

<style lang="scss" scoped>
.App {
  color: skyblue;
}
</style>

бегатьnpm run serveКоманда, если нет ошибки конфигурации, вы можете видеть, что нажатие на разные маршруты переключится на разные представления маршрутизации.

7.2 Настройка отложенной загрузки маршрутизации

В случае маршрута не настроена ленивая загрузка, компонент маршрутизации в нашей упаковке, что они будут упакованы в одинjsфайл, когда у нас будет все больше и больше компонентов представления, это вызовет этоjsФайлы становятся все больше и больше. Тогда это приведет к увеличению времени запроса этого файла, что в конечном итоге повлияет на работу пользователя.

  1. Установить зависимости
npm install @babel/plugin-syntax-dynamic-import --save-dev
  1. Исправлятьbabel.config.js
module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        useBuiltIns: "usage"
      }
    ]
  ],
  plugins: [
     // 添加这个
    '@babel/plugin-syntax-dynamic-import'
  ]
}
  1. Исправлятьrouter/index.jsфайл конфигурации маршрутизации
import Vue from 'vue'
import VueRouter from "vue-router";
Vue.use(VueRouter)
export default new VueRouter({
  mode: 'hash',
  routes: [
    {
      path: '/Home',
      component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
      // component: Home
    },
    {
      path: '/About',
      component: () => import(/* webpackChunkName: "About" */ '../views/About.vue')
      // component: About
    },
    {
      path: '*',
      redirect: '/Home'
    }
  ]
})
  1. Команда выполненияnpm run buildПроверьте, сгенерировано ли оноHome...jsфайл иAbout...jsдокумент

7.3 Интеграция Vuex

  1. существуетsrcСоздайте новый в каталогеstore/index.jsдокумент
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
  counter: 0
}
const actions = {
  add: ({commit}) => {
    return commit('add')
  }
}
const mutations = {
  add: (state) => {
    state.counter++
  }
}
const getters = {
  getCounter (state) {
    return state.counter
  }
}
export default new Vuex.Store({
  state,
  actions,
  mutations,
  getters
})
  1. Исправлятьmain.jsимпорт файловvuex
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'  // ++
new Vue({
  router,
  store,    // ++
  render: h => h(App)
}).$mount('#app')
  1. ИсправлятьApp.vue, проверьте эффект конфигурации vuex
// App.vue
<template>
  <div class="App">
    <div>
      <router-link to="/Home">go Home</router-link>
      <router-link to="/About">go About</router-link>
    </div>
    <div>
      <p>{{getCounter}}</p>
      <button @click="add">add</button>
    </div>
    <div>
      <router-view></router-view>
    </div>
  </div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
  name: 'App',
  data() {
    return {};
  },
  computed: {
    ...mapGetters(['getCounter'])
  },
  methods: {
    ...mapActions(['add'])
  }
};
</script>
<style lang="scss" scoped>
.App {
  text-align: center;
  color: skyblue;
  font-size: 28px;
}
</style>
  1. Команда выполненияnpm run serve

При нажатии на кнопку мы можем увидеть нашgetCounterувеличивается

8 Резюме

На данный момент мы успешно построилиvueСреда разработки, но есть еще некоторые функции, которых не хватает, и заинтересованные партнеры могут общаться. В процессе строительства еще будет много ям.

Если вы не знакомы с webpack, рекомендуется собрать его самостоятельно. получить более глубокое пониманиеvue-cliчто это сделало для нас

Код проекта:GitHub.com/Len too/vUE-…

Рекомендуемое чтение

  1. Используйте различные плагины webpack, чтобы повысить эффективность разработки

  2. Проект Vue-cli3 от оптимизации сборки до развертывания докера

  3. Event Loop оказался делом

  4. Создайте приложение SSR с помощью vue-cli3.

Добро пожаловать, чтобы следовать

Добро пожаловать в общедоступный номер»разработка кода», делясь последней технической информацией каждый день

image