Cómo crear una aplicación Vue.js usando componentes de un solo archivo, sin la CLI.

Comprender los componentes de un solo archivo (SFC) de Vue y el Administrador de paquetes de nodo (NPM) será útil para este artículo.

La interfaz de línea de comandos de un marco, o CLI, es el método preferido para estructurar un proyecto. Proporciona un punto de partida de archivos, carpetas y configuración. Este andamio también proporciona un proceso de desarrollo y construcción. Un proceso de desarrollo proporciona una forma de ver las actualizaciones que ocurren a medida que edita su proyecto. El proceso de construcción crea la versión final de los archivos que se utilizarán en producción.

La instalación y ejecución de Vue.js ("Vue") se puede hacer con una etiqueta de script que apunta a la red de entrega de contenido (CDN) de Vue. No es necesario ningún proceso de construcción o desarrollo. Pero, si usa componentes de archivo único (SFC) de Vue, debe convertir esos archivos en algo que el navegador pueda comprender. Los archivos deben convertirse a lenguaje de marcado de hipertexto (HTML), hojas de estilo en cascada (CSS) y JavaScript (JS). En este caso, se debe utilizar un proceso de desarrollo y construcción.

En lugar de depender de la CLI de Vue para crear un andamio en nuestro proyecto y brindarnos un proceso de desarrollo y construcción, construiremos un proyecto desde cero. Crearemos nuestro propio proceso de desarrollo y construcción utilizando Webpack.

¿Qué es Webpack?

Webpack es un paquete de módulos. Fusiona código de varios archivos en uno. Antes de Webpack, el usuario incluía una etiqueta de secuencia de comandos para cada archivo JavaScript. Aunque los navegadores admiten lentamente los módulos ES6, Webpack sigue siendo la forma preferida de crear código modular.

Además de ser un paquete de módulos, Webpack también puede transformar código. Por ejemplo, puede tomar webpack moderna JavaScript (ECMAScript 6+) y convertirlo en ECMAScript 5. Mientras webpack lía el código en sí, se transforma el código con cargadores y plugins. Piense en cargadores y complementos como complementos para Webpack.

Webpack y Vue

Los componentes de un solo archivo nos permiten construir un componente completo (estructura, estilo y función) en un solo archivo. Y, la mayoría de los editores de código proporcionan resaltado de sintaxis y linchado para estos SFC.

Observe que el archivo termina en .vue. El navegador no sabe qué hacer con esa extensión. Webpack, mediante el uso de cargadores y complementos, transforma este archivo en HTML, CSS y JS que el navegador puede consumir.

El proyecto: crear una aplicación Hello World Vue con componentes de un solo archivo.

Paso 1: crea la estructura del proyecto

El proyecto de Vue más básico incluirá un archivo HTML, JavaScript y Vue (el archivo que termina en .vue ). Colocaremos estos archivos en una carpeta llamada src. La carpeta fuente nos ayudará a separar el código que estamos escribiendo del código que Webpack eventualmente construirá.

Como usaremos Webpack, necesitamos un archivo de configuración de Webpack.

Además, usaremos un compilador llamado Babel. Babel nos permite escribir código ES6 que luego compila en ES5. Babel es una de esas "funciones complementarias" para Webpack. Babel también necesita un archivo de configuración.

Finalmente, dado que estamos usando NPM, también tendremos una carpeta node_modules y un archivo package.json. Estos se crearán automáticamente cuando inicialicemos nuestro proyecto como un proyecto de NPM y comencemos a instalar nuestras dependencias.

Para comenzar, cree una carpeta llamada hello-world. Desde la línea de comando, cambie a ese directorio y ejecute npm init. Siga las instrucciones en pantalla para crear el proyecto. Luego, cree el resto de carpetas (excepto node_modules) como se describe arriba. La estructura de su proyecto debería verse así:

Paso 2: instalar las dependencias

Aquí hay un resumen rápido de las dependencias que estamos usando:

vue : el marco de JavaScript

vue-loader y vue-template-compiler : se utilizan para convertir nuestros archivos Vue en JavaScript.

webpack : La herramienta que nos permitirá pasar nuestro código a través de algunas transformaciones y empaquetarlo en un solo archivo.

webpack-cli: necesario para ejecutar los comandos de Webpack.

webpack-dev-server : aunque no es necesario para nuestro pequeño proyecto (ya que no realizaremos ninguna solicitud HTTP), todavía "serviremos" nuestro proyecto desde un servidor de desarrollo.

babel-loader : Transforma nuestro código ES6 en ES5. (Necesita ayuda de las siguientes dos dependencias).

@ babel / core y @ babel / preset-env : Babel por sí solo no afecta su código. Estos dos "complementos" nos permitirán transformar nuestro código ES6 en código ES5.

css-loader: Toma el CSS que escribimos en nuestro.vuearchivos o cualquier CSS que podamos importar a cualquiera de nuestros archivos JavaScript y resolver la ruta a esos archivos. En otras palabras, averigüe dónde está el CSS. Este es otro cargador que por sí solo no hará mucho. Necesitamos que el siguiente cargador haga algo con el CSS.

vue-style-loader : Tome el CSS que obtuvimos de nuestro css-loadere inyéctelo en nuestro archivo HTML. Esto creará e inyectará una etiqueta de estilo en el encabezado de nuestro documento HTML.

html-webpack-plugin : tome nuestro index.html e inyecte nuestro archivo JavaScript incluido en la cabecera. Luego, copie este archivo en eldistcarpeta.

rimraf : Nos permite, desde la línea de comandos, borrar archivos. Esto será útil cuando construyamos nuestro proyecto varias veces. Usaremos esto para eliminar cualquier compilación anterior.

Instalemos estas dependencias ahora. Desde la línea de comando, ejecute:

npm install vue vue-loader vue-template-compiler webpack webpack-cli webpack-dev-server babel-loader @babel/core @babel/preset-env css-loader vue-style-loader html-webpack-plugin rimraf -D

Nota: La "-D" al final marca cada dependencia como una dependencia de desarrollo en nuestro package.json. Estamos agrupando todas las dependencias en un archivo, por lo que, para nuestro pequeño proyecto, no tenemos dependencias de producción.

Paso 3: Cree los archivos (excepto nuestro archivo de configuración de Webpack).

 {{ message }} export default { data() { return { message: 'Hello World', }; }, };   #app { font-size: 18px; font-family: 'Roboto', sans-serif; color: blue; } 
  Vue Hello World 
import Vue from 'vue'; import App from './App.vue'; new Vue({ el: '#app', render: h => h(App), });
module.exports = { presets: ['@babel/preset-env'], }

Hasta este punto, nada debería parecer demasiado extraño. He mantenido cada archivo muy básico. Solo agregué CSS y JS mínimos para ver nuestro flujo de trabajo en acción.

Paso 4: Indicar a Webpack qué hacer

Toda la configuración a la que Webpack necesita acceder está ahora presente. Necesitamos hacer dos cosas finales: decirle a Webpack qué hacer y ejecutar Webpack.

A continuación se muestra el archivo de configuración de Webpack ( webpack.config.js). Cree este archivo en el directorio raíz de proyectos. Línea por línea discutiremos lo que está ocurriendo.

const HtmlWebpackPlugin = require('html-webpack-plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = { entry: './src/main.js', module: { rules: [ { test: /\.js$/, use: 'babel-loader' }, { test: /\.vue$/, use: 'vue-loader' }, { test: /\.css$/, use: ['vue-style-loader', 'css-loader']}, ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', }), new VueLoaderPlugin(), ] };

Líneas 1 y 2: Estamos importando los dos complementos que usamos a continuación. Tenga en cuenta que nuestros cargadores normalmente no necesitan ser importados, solo nuestros complementos. Y en nuestro caso, elvue-loader (que usamos en la línea 9) también necesita un complemento para funcionar (sin embargo, Babel, por ejemplo, no lo hace).

Línea 4: Exportamos nuestra configuración como objeto. Esto nos da acceso a él cuando ejecutamos los comandos de Webpack.

Línea 5: Este es nuestro módulo de entrada. Webpack necesita un lugar para comenzar. Busca en nuestro main.jsarchivo y luego comienza a peinar nuestro código desde ese punto.

Línea 6 y 7: Este es el objeto del módulo. Aquí, pasamos principalmente una serie de reglas. Cada regla le dice a Webpack cómo manejar ciertos archivos. Entonces, mientras Webpack usa el punto de entrada de main.jspara comenzar a peinar nuestro código, usa las reglas para transformar nuestro código.

Línea 8 (regla): esta regla le indica a Webpack que use babel-loaderen cualquier archivo que termine con .js. Recuerde, Babel transformará ES6 + en ES5.

Línea 9 (regla): esta regla le indica a Webpack que usevue-loader(y no olvide el complemento asociado en la línea 17) para transformar nuestros .vuearchivos en JavaScript.

Línea 10 (regla): A veces queremos pasar un archivo a través de dos cargadores. Contrariamente a la intuición, Webpack pasará el archivo de derecha a izquierda en lugar de de izquierda a derecha. Aquí estamos usando dos cargadores y diciendo a Webpack: “obtén mi CSS de mi archivo Vue o cualquier archivo JavaScript ( css-loader) e inyéctelo en mi HTML como una etiqueta de estilo ( vue-style-loader).

Líneas 11 y 12: cierre nuestra matriz de reglas y el objeto de módulo.

Líneas 13: Cree una matriz de complementos. Aquí agregaremos los dos complementos que necesitamos.

Línea: 14 -16 (plug-in): La HtmlWebpackPlugintoma de la ubicación de nuestro index.html archivo y agrega nuestro archivo JavaScript liado a ella a través de una etiqueta de script. Este complemento también copiará el archivo HTML a nuestra carpeta de distribución cuando construyamos nuestro proyecto.

Línea 17 (plug-in): Los VueLoaderPlugintrabajos con nuestra vue-loaderpara analizar nuestros .vuearchivos.

Línea 18: cierre la matriz de complementos.

Línea 19: Cierre el objeto Webpack que estamos exportando.

Paso 5: Configurar nuestro archivo package.json para que podamos ejecutar Webpack

Nuestra configuración está completa, ahora queremos ver nuestra aplicación. Idealmente, a medida que realizamos cambios en nuestra aplicación, el navegador se actualizaría automáticamente. Esto es posible con webpack-dev-server.

Delete the test script in our package.json file, and replace it with a script to serve our application:

 { "name": "hello-world", "version": "1.0.0", "description": "", "main": "main.js", "scripts": { "serve": "webpack-dev-server --mode development" }, "author": "", "license": "ISC", "devDependencies": { "@babel/core": "^7.1.6", "@babel/preset-env": "^7.1.6", "babel-loader": "^8.0.4", "css-loader": "^1.0.1", "html-webpack-plugin": "^3.2.0", "rimraf": "^2.6.2", "vue": "^2.5.17", "vue-loader": "^15.4.2", "vue-style-loader": "^4.1.2", "vue-template-compiler": "^2.5.17", "webpack": "^4.26.0", "webpack-cli": "^3.1.2", "webpack-dev-server": "^3.1.10" }, "dependencies": {} }

The name of this command is your choice. I chose to call mine serve since we will be serving our application.

From our terminal or command line, we can run npm run serve and that in turn will run webpack-dev-server --mode development .

The --mode development is what’s called a flag or option. We haven’t talked about this, but it essentially instructs Webpack that you are in development mode. We can also pass in --mode production which we will do when we build our project. These aren’t necessarily required for Webpack to work. Without these, you will get a warning message telling you to provide a mode when you run Webpack .

I say “necessarily required” because Webpack will minimize our code in production mode but not in development. So, don’t think those commands don’t do anything–they do.

Let’s run npm run serve and see what happens.

When we run npm run serve we get some output in our terminal. And, if everything goes well:

And if we scroll up a bit:

Point your browser to //localhost:8080. You will see your Blue Hello World message in Roboto font.

Now, let’s update the project and change the message to Hello Universe. Notice that the webpage refreshes automatically. That’s great, right? Can you think of a downside?

Let’s change the application just a bit and include an input which we will bind a variable to (with v-model). We will output the variable in an

tag below the input. I’ve also updated the styling section to style the message now. Our App.vuefile should look like this:

{{ message }}

export default { data() { return { message: 'Hello world!', }; }, }; .message { font-size: 18px; font-family: 'Roboto', sans-serif; color: blue; }

When we serve our application, we will have an input with a message of Hello World below it. The input is bound to the message variable, so as we type, we change the

content. Go ahead, type into the input to change the

content.

Now go back to your editor, and below the

tag, add the following:

Some Other Message

Save your App.vue and watch what happens.

The h2 we just updated by typing in our input reverted back to Hello World. This is because the browser actually refreshes, and the script tag and page are loaded again. In other words, we were not able to maintain the state of our application. This may not seem like a big deal, but as you are testing your application and adding data to it, it will be frustrating if your app “resets” every time. Fortunately, Webpack offers us a solution called Hot Module Replacement.

The hot module replacement is a plugin provided by Webpack itself. Up until this point, we have not used the Webpack object itself in our configuration file. However, we will now import Webpack so we can access the plugin.

In addition to the plugin, we will pass one additional option to Webpack, the devServer option. In that option, we will set hot to true. Also, we will make an (optional) update to our build workflow: We will open the browser window automatically when we run npm run serve. We do this by setting open to true which is also inside the devServer option.

const HtmlWebpackPlugin = require('html-webpack-plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const webpack = require('webpack'); module.exports = { entry: './src/main.js', module: { rules: [ { test: /\.js$/, use: 'babel-loader' }, { test: /\.vue$/, use: 'vue-loader' }, { test: /\.css$/, use: ['vue-style-loader', 'css-loader']}, ] }, devServer: { open: true, hot: true, }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', }), new VueLoaderPlugin(), new webpack.HotModuleReplacementPlugin(), ] };

Notice that we’ve imported Webpack so we could access the hotModuleReplacementPlugin. We’ve added that to the plugins array, and then told Webpack to use it with hot: true. We open the browser window automatically when we serve the application with open: true.

Run npm run serve:

The browser window should open, and if you open your dev tools, you should notice a slight change in the output. It now tells us hot module replacement is enabled. Let’s type in our input to change the

content. Then, change theh3 tag to read: One More Message.

Save your file and notice what happens.

The browser doesn't refresh, but our

change is reflected! The message we typed in the input remains, but the h3 updates. This allows our application to keep it’s state while we edit it.

Step 7: Building our project

So far, we’ve served our application. But, what if we want to build our application so we can distribute it?

If you noticed, when we serve our application, no files are created. Webpack creates a version of these files that only exist in temporary memory. If we want to distribute our Hello World app to our client, we need to build the project.

This is very simple. Just like before, we will create a script in our package.json file to tell Webpack to build our project. We will use webpack as the command instead of webpack-dev-server. We will pass in the --mode production flag as well.

We will also use the rimraf package first to delete any previous builds we may have. We do this simply by rimraf dist.

dist is the folder Webpack will automatically create when it builds our project. “Dist” is short for distribution–i.e. we are “distributing” our applications code.

The rimraf dist command is telling therimraf package to delete the dist directory. Make sure you don’t rimraf src by accident!

Webpack also offers a plugin that will accomplish this cleaning process called clean-webpack-plugin. I chose dist show an alternative way.

Our package.json file should look like this:

{ "name": "hello-world", "version": "1.0.0", "description": "", "main": "main.js", "scripts": { "clean": "rimraf dist", "build": "npm run clean && webpack --mode production", "serve": "webpack-dev-server --mode development" }, "author": "", "license": "ISC", "devDependencies": { "@babel/core": "^7.1.6", "@babel/preset-env": "^7.1.6", "babel-loader": "^8.0.4", "css-loader": "^1.0.1", "html-webpack-plugin": "^3.2.0", "rimraf": "^2.6.2", "vue": "^2.5.17", "vue-loader": "^15.4.2", "vue-style-loader": "^4.1.2", "vue-template-compiler": "^2.5.17", "webpack": "^4.26.0", "webpack-cli": "^3.1.2", "webpack-dev-server": "^3.1.10" }, "dependencies": {} }

There are three things to notice:

  1. I’ve created a separate clean script so we can run it independently of our build script.
  2. npm run build will call the independent clean script we’ve created.
  3. I have && between npm run clean and webpack. This instruction says: “run npm run clean first, then run webpack”.

Let’s build the project.

npm run build

Webpack creates a dist directory, and our code is inside. Since our code makes no HTTP requests, we can simply open our index.html file in our browser and it will work as expected.

If we had code that was making HTTP requests, we would run into some cross-origin errors as we made those requests. We would need to run that project from a server for it to work.

Let’s examine the index.html that Webpack created in the browser and the code editor.

If we open it in our editor or take a look at the source code in our dev tools you will see Webpack injected the script tag. In our editor though, you won’t see the styles because the style tag is injected dynamically at runtime with JavaScript!

Also, notice our development console information is no longer present. This is because we passed the --production flag to Webpack.

Conclusion

Understanding the build process behind the frameworks you use will help you to better understand the framework itself. Take some time to try to build an Angular, React or another Vue Project without the use of the respective CLIs. Or, just build a basic three-file site (index.html, styles.css, and app.js), but use Webpack to serve and build a production version.

Thanks for reading!

woz