Webpack4 здесь официально! Вы знали, что они называют это Легато! Есть много новых функций и улучшений. Игра Шона Т. Ларкина в Webpack 4 поднялась на 3 уровня. Вы можете прочитать об изменениях в этой статье или здесь, в git-changelog.
Короче говоря, Webpack4 на 98% быстрее. У них есть Mode, # 0CJS и разумные настройки по умолчанию. 😻 Он имеет разбиение на части как настраиваемое значение по умолчанию для различных режимов. Типы модулей представлены вместе с поддержкой .mjs и поддержкой WebAssembly. Javascript будущего уже здесь! 💥
Я перенес один базовый стартер VueJs на Webpack4, и это оказалось довольно легко. У меня было немного сбоев, потому что некоторые плагины еще не обновлены для Webpack 4. Но как только появится необходимая поддержка, портирование существующих проектов до последней версии займет несколько минут. Я начал с # 0CJS (Zero-Config JS), в котором используются режимы по умолчанию, но как только я интегрировал Vue, я добавил несколько базовых конфигураций для создания начального проекта, который включает маршрутизацию, тестирование и настраиваемый файл HTML.
Что касается кода: я использовал режимы 0-Configuration для сборок производства / разработки и использовал webpack-dev-server для целей разработки. Я добавил все статьи по теме, которые смог найти о Webpack4, в конце этой статьи, чтобы упростить процесс миграции. Каждый подзаголовок указывает на код репозитория Git, вы также можете напрямую проверить его оттуда, щелкнув заголовки.
- Package.json: 📁
Мой первоначальный package.json прост. Скрипт для разработки, сборки и для webpack-dev-server. Также есть скрипты для тестирования.
{ "name": "webpack-4-quickstart", "version": "1.0.0", "description": "> Webpack 4 tutorial: VueJs starter-kit, from 0 Conf to Production Mode", "main": "index.js", "scripts": { "start": "cross-env NODE_ENV=development webpack-dev-server --inline --hot", "dev": "webpack --mode development", "build": "webpack --mode production", "test": "node_modules/.bin/karma start", "test-grep": "node_modules/.bin/karma start --grep" }, "repository": { "type": "git", "url": "git+https://https://github.com/nnupoor/webpack4vue.git" }, "keywords": [], "author": "Neha Nupoor", "license": "MIT", "bugs": { "url": "https://github.com/nnupoor/webpack4vue/issues" }, "homepage": "https://github.com/nnupoor/webpack4vue#readme", "devDependencies": { "autoprefixer-loader": "^3.2.0", "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-env": "^1.6.1", "chai": "^4.1.1", "cross-env": "^5.1.3", "css-loader": "^0.23.1", "extract-text-webpack-plugin": "^2.1.0", //not working currently. "file-loader": "^0.8.4", "html-webpack-plugin": "webpack-contrib/html-webpack-plugin", //is a patch right now. "inject-loader": "^3.0.1", "istanbul": "^0.4.5", "karma": "^1.7.0", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^2.2.0", "karma-coverage": "^1.1.1", "karma-mocha": "^1.3.0", "karma-requirejs": "^1.1.0", "karma-sinon": "^1.0.5", "karma-webpack": "^2.0.4", "karma-webpack-grep": "^1.0.1", "mocha": "^3.5.0", "node-sass": "^4.5.3", "requirejs": "^2.3.5", "sass-loader": "^6.0.5", "sinon": "^3.2.1", "style-loader": "^0.14.1", "surge": "^0.18.0", "svg-sprite-generator": "0.0.7", "svg-sprite-loader": "^0.3.0", "vue-loader": "^14.1.1", "vue-template-compiler": "^2.5.13", "vue-resource": "^1.2.1", "vue-router": "^2.3.0", "webpack": "^4.0.0", "webpack-cli": "^2.0.8", "webpack-dev-server": "^3.0.0", "webpack-serve": "^0.1.4" }, "dependencies": { "vue": "^2.5.13" } }
2. Файл webpack.config.js: 💣
После того, как вы настроили package.json, пора настроить файл webpack.config.js. Я создал базовый файл, но его можно разделить или улучшить. Этого должно быть достаточно, чтобы вы начали.
const path = require('path'); const fs = require('fs'); const webpack = require('webpack'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const NODE_ENV = process.env.NODE_ENV; const setPath = function(folderName) { return path.join(__dirname, folderName); } const isProd = function() { return (process.env.NODE_ENV === 'production') ? true : false; } const buildingForLocal = () => { return (NODE_ENV === 'development'); }; const setPublicPath = () => { let env = NODE_ENV; if (env === 'production') { return 'https://your-host.com/production/'; } else if (env === 'staging') { return 'https://your-host.com/staging/'; } else { return '/'; } }; const extractCSS = new ExtractTextPlugin({ filename: "css/styles.[hash].css",//"[name].[contenthash].css", disable: process.env.NODE_ENV === "development" }); const extractHTML = new HtmlWebpackPlugin({ title: 'History Search', filename: 'index.html', inject: true, template: setPath('/src/tpl/tpl.ejs'), environment: process.env.NODE_ENV, isLocalBuild: buildingForLocal(), imgPath: (!buildingForLocal()) ? 'assets' : 'src/assets' }); const config = { /** * You can use these too for bigger projects. For now it is 0 conf mode for me! */ // entry: { // build: path.join(setPath('src'), 'main.js'), // vendor: path.join('setPath('src'), 'vendor.js') // }, // output: { // path: buildingForLocal() ? path.resolve(__dirname) : setPath('dist'), //this one sets the path to serve // publicPath: setPublicPath(), // filename: buildingForLocal() ? 'js/[name].js' : 'js/[name].[hash].js' // }, optimization:{ runtimeChunk: false, splitChunks: { chunks: "all", //Taken from https://gist.github.com/sokra/1522d586b8e5c0f5072d7565c2bee693 } }, resolveLoader: { modules: [setPath('node_modules')] }, mode: buildingForLocal() ? 'development' : 'production', devServer: { historyApiFallback: true, noInfo: false }, plugins: [ extractHTML, // extractCSS, new webpack.DefinePlugin({ 'process.env': { isStaging: (NODE_ENV === 'development' || NODE_ENV === 'staging'), NODE_ENV: '"'+NODE_ENV+'"' } }) ], module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { js: 'babel-loader' } } }, { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: [{ loader: "babel-loader", options: { presets: ['es2015'] } }] }, { test: /\.css$/, use: extractCSS.extract({ fallback: "style-loader", use: ["css-loader", "autoprefixer-loader"] }) }, { test: /\.scss$/, use: !buildingForLocal() ? extractCSS.extract({ fallback: "style-loader", use: ['css-loader', 'autoprefixer-loader', 'sass-loader'] }) : [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "sass-loader" // compiles Sass to CSS }] }, { test: /\.svg$/, loader: 'svg-sprite-loader' }, { test: /\.(png|jpg|gif)$/, loader: 'file-loader', query: { name: '[name].[ext]?[hash]', useRelativePath: buildingForLocal() } } ] }, }; module.exports = config;
2.1 Настройка HtmlWebpackPlugin: 🍫
Для упрощения я использовал HtmlWebpackPlugin, чтобы взять шаблон .ejs и заполнить его сгенерированными пакетами js / css. HtmlWebpackPlugin официально не работает, но я пока использовал патч, предоставленный webpack.
const extractHTML = new HtmlWebpackPlugin({ title: 'History Search', filename: 'index.html', inject: true, template: setPath('/src/tpl/tpl.ejs'), environment: process.env.NODE_ENV, isLocalBuild: buildingForLocal(), imgPath: (!buildingForLocal()) ? 'assets' : 'src/assets' }) // Inside config object const config = { . . plugins: [extractHTML], }
2.2 Извлечение CSS с помощью ExtractTextPlugin: 🙅🏻
Затем мы берем ExtractTextPlugin и извлекаем CSS, чтобы облегчить разделение CSS. Теперь этот плагин не работает сейчас. (* Изменить: они выпустили бета-версию плагина, о которой я не знал. Шон Т. Ларкин указал на это, и я обновил код, чтобы он работал. *)
const extractCSS = new ExtractTextPlugin({ filename: "css/styles.[hash].css",//"[name].[contenthash].css", disable: process.env.NODE_ENV === "development" }); // Inside config object const config = { . . plugins: [extractHTML], }
2.3 Настройка конфигурации режима: ✋🏻
Мы также можем установить режим конфигурации веб-пакета явно в объекте конфигурации.
const config = { . . mode: buildingForLocal() ? 'development' : 'production' }
2.4 Настройка конфигурации оптимизации: 🎯
Вы также можете настроить объект оптимизация. Такие плагины, как NoEmitOnErrorsPlugin, ModuleConcatenationPlugin, NamedModulesPlugin перемещаются в конфигурацию оптимизации, и для них установлены значения по умолчанию в зависимости от выбранного вами режима. CommonsChunkPlugin был удален, его конфигурация теперь находится внутри объекта оптимизации. Его можно настроить следующим образом:
optimization:{ runtimeChunk: false, splitChunks: { chunks: "all", //Taken from https://gist.github.com/sokra/1522d586b8e5c0f5072d7565c2bee693 } }
Одна хорошая вещь в этой миграции заключалась в том, что я смог выяснить свои ошибки, просто прочитав ошибки консоли. Я сделал много ошибок при настройке вышеуказанного параметра, и мне легко удалось настроить его правильно благодаря информативным ошибкам, которые я получал. 🧀
2.5 Настройка конфигурации devServer для webpack-dev-server: 🎢
Теперь настраиваем devServer. Я заметил одну вещь: если я установил noInfo: true, то я не получал никакой информации о порте, на котором работает мой сервер, в отличие от предыдущих версий. Чтобы прийти к каким-либо выводам, нужно вникнуть в него глубже. Пока это неправда.
devServer: { noInfo: false }
2.6 Настройка модулей: ⚓️
Ничего особенного, только старые Vue, JS, CSS, SCSS, SVG и загрузчики изображений.
module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { // postcss: [require('postcss-cssnext')()] // options: { // extractCSS: true // } loaders: { js: 'babel-loader' } } }, { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: [{ loader: "babel-loader", options: { presets: ['es2015'] } }] }, // { // test: /\.css$/, // use: extractCSS.extract({ // fallback: "style-loader", // use: ["css-loader", "autoprefixer-loader"] // }) // }, { test: /\.scss$/, use: //!buildingForLocal() ? // extractCSS.extract({ // fallback: "style-loader", // use: ['css-loader', 'autoprefixer-loader', 'sass-loader'] // }) : [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "sass-loader" // compiles Sass to CSS }] }, { test: /\.svg$/, loader: 'svg-sprite-loader' }, { test: /\.(png|jpg|gif)$/, loader: 'file-loader', query: { name: '[name].[ext]?[hash]', useRelativePath: buildingForLocal() } } ] }
Если вы видите, я закомментировал функции extractCSS. Они не работали. Использование CSS в Vue для победы! 🥊 (* Изменить: сейчас работает. См. Выше. *)
Вот и все. Это базовая конфигурация / миграция для webpack 4, которую мне нужно было сделать, чтобы запустить простой проект VueJs с нуля. Я добавил базовые тесты, маршрутизацию, следил за структурой каталогов страницы, макета и компонентов.
Примечание: в приведенном выше коде я удалил несколько строк для простоты объяснения, репозиторий Git имеет весь необходимый код, чтобы любой мог начать работу с VueJs и Webpack 4. Я хочу изучить и открыть для всех обратная связь, которую вы все можете предложить.
NOTE: This code has been updated on git for webpack v4.1.1 and modules like "mini-css-extract-plugin" have been added which are released recently. Take a look at the code, if not, most of the issues with plugins have been sorted by now. Happy coding! :)
- Заявление о выпуске Webpack4: https://medium.com/webpack/webpack-4-released-today-6cdb994702d4
- Руководство по миграции Webpack4 для загрузчиков / плагинов: https://medium.com/webpack/webpack-4-migration-guide-for-plugins-loaders-20a79b927202
- Режимы Webpack: https://medium.com/webpack/webpack-4-mode-and-optimization-5423a6bc597a
- Журналы выпуска Webpack4: https://github.com/webpack/webpack/releases
- Webpack4 SplitChunks: https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
- Webpack CommonchunksPlugin: https://gist.github.com/sokra/1522d586b8e5c0f5072d7565c2bee693
- Документация по Webpack: https://webpack.js.org/guides/
Если вы нашли статью полезной и знаете это, хлопайте в ладоши! Это сделало бы меня таким 😍