Construindo um ambiente de desenvolvimento Vue com Webpack do zero

Ao trabalhar com Vue, frequentemente utilizamos o vue-cli para configurar rapidamente o ambiente de desenvolvimento. Embora o vue-cli seja uma excelente ferramenta que nos permite começar a escrever código de negócio sem nos preocuparmos com configurações complexas do webpack, isso pode criar uma dependência excessiva e obscurecer a importância do webpack. Em cenários especiais, como configuração de múltiplas entradas em Vue ou otimização da velocidade de empacotamento, essa falta de compreensão pode se tornar problemática.

O código-fonte relacionado a este artigo está disponível no repositório https://github.com/WindrunnerMax/webpack-simple-environment, na branch webpack--vue-cli. Por padrão, o webpack suporta apenas arquivos js e json, então precisamos converter arquivos css, img, html, vue e outros em formato JavaScript para que o webpack possa processá-los. O foco principal ao construir um ambiente de desenvolvimento Vue é lidar com componentes de arquivo único (.vue), exigindo principalmente loaders adequados.

Configuração inicial

Vamos começar criando um ambiente webpack básico. Primeiro, inicializamos o projeto e instalamos as dependências:

$ yarn init -y
$ yarn add -D webpack webpack-cli cross-env

Podemos testar o empacotamento do webpack com configuração zero. A estrutura do diretório é:

webpack-simple
├── package.json
├── src
│   ├── index.js
│   └── calculate.js
└── yarn.lock

// src/calculate.js
export const multiply = (x, y) => x * y;

// src/index.js
import { multiply } from "./calculate";
console.log(multiply(2, 3));

Adicionamos um comando de build no package.json:

// package.json
{
    // ...
    "scripts": {
        "build": "webpack"
    },
    // ...
}

Executamos npm run build e o webpack cria automaticamente uma pasta dist com o arquivo main.js:

(()=>{"use strict";console.log(6)})();

Arquivo de configuração do Webpack

Normalmente não usamos configuração zero. Criamos um arquivo webpack.config.js:

// package.json
{
    // ...
    "scripts": {
        "build": "cross-env NODE_ENV=production webpack --config webpack.config.js"
    },
    // ...
}

const path = require("path");
module.exports = {
    mode: process.env.NODE_ENV,
    entry: "./src/index.js",
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "dist")
    }
}

Plugin HtmlWebpackPlugin

Para processar arquivos HTML, usamos o plugin html-webpack-plugin:

$ yarn add -D html-webpack-plugin

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    mode: process.env.NODE_ENV,
    entry: "./src/index.js",
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "dist")
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: "Vue Development Environment", 
            filename: "index.html",
            template: path.resolve("./public/index.html"),
            hash: true,
            minify: {
                collapseWhitespace: true,
                removeAttributeQuotes: true,
                minifyCSS: true,
                minifyJS: true,
            },
            inject: "body",
            scriptLoading: "blocking"
        })
    ]
}

Criamos o arquivo /public/index.html:


<html lang="pt-br">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

Webpack Dev Server

Para desenvolvimento local, usamos o webpack-dev-server:

$ yarn add -D webpack-dev-server

// webpack.config.js
module.exports = {
    devServer: {
        hot: true,
        open: true,
        compress: true,
        port: 8080
    },
    // ...
}

// package.json
"scripts": {
    "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
    "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js"
}

Configuração básica do Vue

Instalamos o Vue e criamos nosso componente principal:

$ yarn add vue

// /src/main.js
import Vue from "vue";

new Vue({
    el: "#app",
    template: "<div>Exemplo Vue</div>"
})

Atualizamos a configuração do webpack para usar o compilador completo do Vue:

module.exports = {
    resolve: {
        alias: {
          "vue$": "vue/dist/vue.esm.js" 
        }
    },
    // ...
}

Processamento de componentes .vue

Criamos um arquivo App.vue e configuramos os loaders necessários:

$ yarn add -D vue-loader vue-template-compiler css-loader vue-style-loader

// main.js
import Vue from "vue";
import App from "./App.vue";

const app = new Vue({
    ...App,
});
app.$mount("#app");

<!-- App.vue -->
<template>
    <div class="container">{{ message }}</div>
</template>

<script>
export default {
    name: "App",
    data: () => ({
        message: "Hello Vue"
    })
}
</script>

<style scoped>
    .container {
        font-size: 24px;
        color: #333;
    }
</style>

const VueLoaderPlugin = require("vue-loader/lib/plugin")

module.exports = {
    module: {
        rules: [
            {
                test: /\.vue$/,
                use: "vue-loader",
            },
            {
                test: /\.css$/,
                use: [
                    "vue-style-loader",
                    "css-loader"
                ],
            },
        ],
    },
    plugins: [
        new VueLoaderPlugin(),
    ]
}

Tratamento de recursos

Para lidar com imagens e outros recursos:

$ yarn add -D url-loader file-loader

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/i,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            esModule: false,
                            limit: 8192,
                            fallback: {
                                loader: "file-loader",
                                options: {
                                    esModule: false,
                                    name: "[name].[hash:8].[ext]",
                                    outputPath: "assets",
                                }
                            },
                        }
                    }
                ]
            },
        ],
    },
}

Configuração do Babel

Para compatibilidade com navegadores antigos:

$ yarn add -D @babel/core @babel/preset-env babel-loader
$ yarn add core-js@3

// babel.config.js
module.exports = {
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": 3,
                "modules": false
            }
        ]
    ]
}

module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: ["babel-loader"]
            },
        ],
    },
}

Processamento de CSS

Para usar Sass e PostCSS:

yarn add -D sass sass-loader@10.1.1 postcss postcss-loader

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    "vue-style-loader",
                    "css-loader",
                    "postcss-loader"
                ],
            },
            {
                test: /\.(scss)$/,
                use: [
                    "vue-style-loader",
                    "css-loader",
                    "postcss-loader",
                    "sass-loader",
                ]
            },
        ],
    },
}

Integração do Vue Router

Instalamos e configuramos o Vue Router:

$ yarn add vue-router

Criamos os componentes e rotas conforme necessário, integrando o sistema de roteamento.

Integração do Vuex

Instalamos e configuramos o Vuex para gerenciamento de estado:

yarn add vuex

Configuramos o store e integramos com nossos componentes.

Configuração do ESLint

Para manter o padrão de código:

$ yarn add -D eslint eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue prettier vue-eslint-parser

Configuramos os arquivos de configuração do ESLint, Prettier e EditorConfig.

Integração do TypeScript

Para adicionar suporte a TypeScript:

yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser @babel/plugin-syntax-typescript typescript vue-property-decorator vue-class-component ts-loader vuex-class

Configuramos o TypeScript com decorators e integração com Vue, incluindo arquivos de declaração e configuração do tsconfig.json.

Tags: webpack vue TypeScript javascript babel

Publicado em 8-31 04:38