DefinePlugin для практичных плагинов для веб-пакетов

Webpack
DefinePlugin для практичных плагинов для веб-пакетов

Прочитав эту статью, вы узнаете, как использовать плагин DefinePlugin, чтобы сделать интерфейсные проекты более инженерными. эффективность фронтенд-разработки.

  • Правильное использование DefinePlugin
  • Как с помощью DefinePlugin добавить конфигурационные файлы для автоматического определения изменений среды во время сборки, то есть как ввести конфигурационные файлы на основе NODE_ENV?

Правильное использование DefinePlugin

Каждый ключ в DefinePlugin является идентификатором или.как несколько идентификаторов.

  • Если значение является строкой, оно будет рассматриваться как фрагмент кода.
  • Если значение не является строкой, оно будет преобразовано в строку (включая функции)
  • Если значение является объектом, все ключи определяются одинаково.
  • если у ключа естьtypeofпрефикс, который определяется только типом вызова.

Эти значения будут встроены в код, сжаты для уменьшения избыточности.

new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(true),
    VERSION: JSON.stringify('5fa3b9'),
    BROWSER_SUPPORTS_HTML5: true,
    TWO: '1+1',
    'typeof window': JSON.stringify('object'),
    'process.env': {
         NODE_ENV: JSON.stringify(process.env.NODE_ENV)
     }
});
console.log('Running App version' + VERSION);

плагин не является прямой заменой текстового значения, его значение должно включаться в строкуфактическая цитата. Типичным случаем является заключение в двойные кавычки или JSON.stringify(), '"production"', JSON.stringify('production').

Основные моменты:В проекте, созданном vue-cli, все файлы в src могут получить доступ к переменной VERSION, например main.js, App.vue и т. д.

Давайте теперь посмотрим на вывод приведенных выше нескольких типов значений ключа в коде.

console.log(PRODUCTION, VERSION, BROWSER_SUPPORTS_HTML5, TWO, typeof window, process.env);
PRODUCTION: true,
VERSION: "5fa3b9",
BROWSER_SUPPORTS_HTML5: true,
TWO: 2,
typeof window: "object",
process.env: {NODE_ENV: "development"},

В коде мы обычно имеем следующее использование:

  • В зависимости от процесса.env.node_env
  • импортировать файл конфигурации
  • Импорт файлов конфигурации на основе NODE_ENV(Это очень важно и будет обсуждаться позже)
Feature Flag

Переключатели, управляющие новыми и экспериментальными функциями.

new webpack.DefinePlugin({
    'NICE_FEATURE': JSON.stringify(true),
    'EXPERIMENTAL': JSON.stringify(false),
})
Как правильно настроить process.env.NODE_ENV?
process: {
    env: {
        NODE_ENV: JSON.stringify('production')
    }
}

оценивать:Очень плохо, он перезапишет весь объект процесса, сохранит только новый NODE_ENV и уничтожит процесс.Исходный объект процесса содержит следующее содержимое, которое содержит много информации о текущем процессе.

process {
  title: 'node',
  version: 'v8.11.2',
  moduleLoadList: 
   [ 'Binding contextify',],
  versions: 
   { http_parser: '2.8.0'},
  arch: 'x64',
  platform: 'darwin',
  release: 
   { name: 'node' },
  argv: [ '/usr/local/bin/node' ],
  execArgv: [],
  env: 
   { TERM: 'xterm-256color'},
  pid: 14027,
  features: 
   { debug: false},
  ppid: 14020,
  execPath: '/usr/local/bin/node',
  debugPort: 9229,
  _startProfilerIdleNotifier: [Function: _startProfilerIdleNotifier],
  _stopProfilerIdleNotifier: [Function: _stopProfilerIdleNotifier],
  _getActiveRequests: [Function: _getActiveRequests],
  _getActiveHandles: [Function: _getActiveHandles],
  reallyExit: [Function: reallyExit],
  abort: [Function: abort],
  chdir: [Function: chdir],
  cwd: [Function: cwd],
  umask: [Function: umask],
  getuid: [Function: getuid],
  geteuid: [Function: geteuid],
  setuid: [Function: setuid],
  seteuid: [Function: seteuid],
  setgid: [Function: setgid],
  setegid: [Function: setegid],
  getgid: [Function: getgid],
  getegid: [Function: getegid],
  getgroups: [Function: getgroups],
  setgroups: [Function: setgroups],
  initgroups: [Function: initgroups],
  _kill: [Function: _kill],
  _debugProcess: [Function: _debugProcess],
  _debugPause: [Function: _debugPause],
  _debugEnd: [Function: _debugEnd],
  hrtime: [Function: hrtime],
  cpuUsage: [Function: cpuUsage],
  dlopen: [Function: dlopen],
  uptime: [Function: uptime],
  memoryUsage: [Function: memoryUsage],
  binding: [Function: binding],
  _linkedBinding: [Function: _linkedBinding],
  _events: 
   { newListener: [Function],
     removeListener: [Function],
     warning: [Function],
     SIGWINCH: [ [Function], [Function] ] },
  _rawDebug: [Function],
  _eventsCount: 4,
  domain: [Getter/Setter],
  _maxListeners: undefined,
  _fatalException: [Function],
  _exiting: false,
  assert: [Function],
  config: {},
  emitWarning: [Function],
  nextTick: [Function: nextTick],
  _tickCallback: [Function: _tickDomainCallback],
  _tickDomainCallback: [Function: _tickDomainCallback],
  stdout: [Getter],
  stderr: [Getter],
  stdin: [Getter],
  openStdin: [Function],
  exit: [Function],
  kill: [Function],
  _immediateCallback: [Function: processImmediate],
  argv0: 'node' }
'process.env': {
    NODE_ENV: JSON.stringify('production')
}

оценивать:Нехорошо, это перезапишет весь объект process.env, разрушит среду процесса и нанесет ущерб совместимости.Исходный объект process.env содержит следующее содержимое, которое содержит много информации о текущем процессе.

{ TERM: 'xterm-256color',
  SHELL: '/bin/bash',
  TMPDIR: '/var/folders/lw/rl5nyyrn4lb0rrpspv4szc3c0000gn/T/',
  Apple_PubSub_Socket_Render: '/private/tmp/com.apple.launchd.dEPuHtiDsx/Render',
  USER: 'frank',
  SSH_AUTH_SOCK: '/private/tmp/com.apple.launchd.MRVOOE7lpI/Listeners',
  __CF_USER_TEXT_ENCODING: '0x1F5:0x19:0x34',
  PATH: '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Wireshark.app/Contents/MacOS',
  PWD: '/Users/frank/Desktop/corporation/weidian-crm',
  XPC_FLAGS: '0x0',
  XPC_SERVICE_NAME: '0',
  SHLVL: '1',
  HOME: '/Users/frank',
  LOGNAME: 'frank',
  LC_CTYPE: 'zh_CN.UTF-8',
  _: '/usr/local/bin/node' }
'process.env.NODE_ENV': JSON.stringify('production')

оценивать:Хорошо. Потому что только изменение значения NODE_ENV не нарушит весь процесс и не нарушит совместимость.

Как с помощью DefinePlugin добавить конфигурационные файлы для автоматического определения изменений среды во время сборки, то есть как ввести конфигурационные файлы на основе NODE_ENV?

Сценарий: адрес интерфейса на этапе разработки часто не соответствует адресу интерфейса на этапе производства. Например, для разработки используется development.foo.com, а для продакшена — production.foo.com.Если вам нужно упаковать и выпустить, вам нужно вручную заменить доменное имя или поддерживать специальный файл конфигурации в ветке. Эти два метода очень громоздки.

  • ручная замена Эффективность файла низкая, каждый раз, когда вы переключаетесь между разработкой и производством, вам нужно обновлять файл конфигурации, который подвержен ошибкам.
  • конфигурационный файл По сравнению с заменой вручную, она является более продвинутой, но не может просматривать всю информацию о конфигурации разработки и производства одновременно, необходимо переключаться между ветвями, что неэффективно и не подходит для настройки нескольких сред.
  • webpack.DefinePlugin() Глобальный файл конфигурации, автоматическое обнаружение изменений окружающей среды, эффективное и действенное.

DefinePlugin веб-пакета решает эту проблему за нас, он поддерживает глобальный файл конфигурации, автоматически определяет process.env.NODE_ENV во время компиляции и заменяет доменное имя нашего интерфейса в соответствии с текущими переменными среды.

Ниже я буду использовать пример, чтобы показать, как правильно использовать webpack.DefinePlugin.

/config/api.js

const NODE_ENV = process.env.NODE_ENV;
const config = {
     production: {
        FOO_API: 'production.foo.api.com',
        BAR_API: 'production.bar.api.com',
        BAZ_API: 'production.baz.api.com',
     },
     development: {
        FOO_API: 'development.foo.api.com',
        BAR_API: 'development.bar.api.com',
        BAZ_API: 'development.baz.api.com',
     },
     test: {
        FOO_API: 'test.foo.api.com',
        BAR_API: 'test.bar.api.com',
        BAZ_API: 'test.baz.api.com',
     }
}
module.exports = config[NODE_ENV];

webpack.dev.conf.js/webpack.prod.conf.js/webpack.test.conf.js

const apiConfig = require('./config/api');
const webpackConfig = {
    plugins: [
        new webpack.DefinePlugin({
            API_CONFIG: JSON.stringify(apiConfig);
        })
    ]
}
...

custom.component.vue

<template>
...
</template>
<script>
// 这里也可以访问到API_CONFIG
export default {
    // 这里无论是data函数,methods对象,computed对象,watch对象,都可以访问到API_CONFIG;
   data() {
       return {
           fooApi: API_CONFIG.FOO_API,
           user:{
               id: '',
               name: '',
           },
           hash: '',
        } 
    },
    computed: {
        userAvator() {
            return `${API_CONFIG.BAR_API}?id=${user.id}&name=${user.name}`
        }
    },
    methods: {
        uploadImage() {
            api.uploadImage({user: `${API_CONFIG.BAZ}\${hash}`})
                 .then(()=>{})
                 .catch(()=>{})
        }
    }
}
</script>

Вышеуказанное просто применимо к возрасту Vue-CLI2.0, Vue-Cli3.0 представила цепочку WeepPack, в основном различных конфигураций, приведен пример.

Как с помощью DefinePlugin добавить конфигурационные файлы в vue.config.js для автоматического определения изменений окружения во время сборки, то есть как ввести конфигурационные файлы на основе NODE_ENV?

vue.config.js

const apiConfig = require('./config/api');

module.exports = {
    chainWebpack: config => {
        config
            .plugin('define')
            .tap(args => { 
                args[0].API_CONFIG = JSON.stringify(apiConfig)
                return args
            })
    }
}

Следует отметить, что в vue-cli3.0 мы не можем напрямую SET NODE_ENV=production или EXPORT NODE_ENV=production. Поскольку vue-cli-servive имеет 3 режима, serve по умолчанию — это разработка, а build — это production.Если вы хотите изменить NODE_ENV в пакете vue-cli-service, вам нужно переключиться через vue-cli-service serve --mode производство. Как следующее:

{
  "scripts": {
    "dev": "vue-cli-service serve", // mode默认为development 
    "production": "vue-cli-service serve --mode production", 
  },
}

Примечание. Мы можем переключаться только между тремя режимами разработки, производства или тестирования, и мы не можем вводить пользовательские среды узлов, такие как предварительная подготовка, но на самом деле этих трех сред достаточно для большинства ситуаций разработки.

Почему DefinePlugin в vue-cli 3.0 можно изменить с помощью config.plugin('define')?

существуетИсходный файл Base.js., есть следующий код:

    webpackConfig
      .plugin('define')
        .use(require('webpack/lib/DefinePlugin'), [
          resolveClientEnv(options)
        ])

Это критично!config.plugin('define'), который мы получили в vue.config.js, на самом деле является ссылкой на экземпляр webpack.DefinePlugin, созданный внутри vue-service!Чтобы прояснить этот момент, когда мы будем улучшать конфигурацию плагина по умолчанию для веб-пакета в будущем, нам нужно найти исходный код vue-service, чтобы увидеть, есть ли ссылка на соответствующий плагин.Если есть, это должно быть напрямую ссылаются в соответствии с именем, определенным vue-service, в противном случае модификация завершится ошибкой.

Я с нетерпением жду возможности пообщаться с вами и вместе добиться прогресса. Приглашаем вас присоединиться к созданной мной технической дискуссионной группе, тесно связанной с фронтенд-разработкой:

Стремитесь стать отличным front-end инженером!