手動實現一個vue cli

手動實現一個vue cli

1. 思考準備

最一開始:創建一個web項目,所以需要一個html 文件,又是一個Vue 項目,所以需要一個div,並指明一個id.

我們使用webpack 打包後的文件,需要被引入,bundle.js, 應該把它放在dist (分發)文件夾。

----> 指明id 的 div 的html 文件
----> dist 文件夾

目前結構爲:

.
└── dist
    └── index.html

index.html 內容爲:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>VueStarter</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="bundle.js"></script>
  </body>
</html>

2. 我們組織源碼將會放在名爲src的目錄,webpack 打包需要一個入口文件,我們取作 main.js

.
├── dist
│   └── index.html
└── src
 └── main.js

3. 先預想以下會用到哪些基本依賴,第一個容易想到的是Vue, 然後是我們假設項目需要使用elementUI , 還有axios ,先就這些:

npm i vue element-ui axios

最終我們需要的核心文件是打包後的bundle.js , 接下來需要用到的核心是webpack , 所以安裝 webpack

以及想到, 需要引入vue 的代碼 vue-loader 以及 .vue 文件的解析依賴 vue-template-compiler

樣式sass-loader 以及sass 本體

處理後的css 文件需要通過css-loader 加載,然後被style 標籤解析,需要用到 style-loader

還需要babel 來處理es6的新語法,所以需要安裝

babel babel-loader @babel/core babel 的預設配置 @babel/preset-env(env 代表兼容最新的語法)

# -D 指的是開發環境
npm i -D webpack webpack-cli vue-loader vue-template-compiler sass-loader sass css-loader style-loader babel-loader @babel/core @babel/preset-env

4. 我們的目標是要把src 中的從main.js 開始去編譯-打包,到dist 文件夾中去, 所以我們需要配置文件,進行配置。 所以創建webpack 的配置文件, webpack.config.js

發現沒有自動生成 package.json 文件, 命令 npm init 手動生成, 將入口文件指定爲main.js

.
├── README.md# 手動生成的
├── dist
├── node_modules
├── package-lock.json
├── package.json
├── src
└── webpack.config.js

5. 編寫配置:

基本結構熟悉:

module.exports = {
entry:'',//入口文件
output:{//出口文件,
 path:'',
 filename:'',
},
module:{//webpack 中一切皆模塊
 rules:[
   { test:/\.vue$/,use:'vue-loader'},
   ....
 ]
},
plugins:[//插件用於增強webpack
 new PluginsA(),//每一個插件就是一個實例
 new PluginsB(),
 ...
]
}

開始填充內容:

const path = require("path");
const { VueLoaderPlugin } = require("vue-loader");
module.exports = {
entry: "./src/main.js", //入口文件 絕對路徑 / 相對路徑
output: {
 //出口文件,
 path: path.resolve(__dirname, "dist") + "", //絕對路徑 __dirname 是node "當前所在路徑pwd" , 由於window 的目錄分隔符是 '\', 而類nix是 '/', 爲了保持靈活性,使用了node 內置的path 對象方法,將自動將當前系統目錄分隔符和目錄名拼接
 filename: "bundle.js",
},
module: {
 //webpack 中一切皆模塊
 rules: [
   { test: /\.vue$/, use: "vue-loader" },
   /**
    * 處理.vue 文件的加載, 寫法可以指定
    * 單個依賴 - String,
    * 單個帶配置的依賴 - {}
    * 多個不帶配置的依賴 - []String ,
    * 多個帶配置的依賴 []Object
    * { test: /\.vue$/, use: [{loader:'vue-loader',options:{}},{}...] },
    */
   {
     test: /\.s[ca]ss$/,
     use: ["style-loader", "css-loader", "scss-loader"],
   }, //要注意順序,依次從後往前解析
   {
     test: /\.m?js$/, //.msj 是es6 的模塊化js 文件
     use: {
       loader: "babel-loader",
       options: {
         presets: ["@babel/preset-env"],
       },
     },
   },
   {
     //圖片處理
     // test: /\.(png|jpe?g|gif|svg|webp)$/,use: { laoder: "file-loader", options: { esModule: false } },//老語法
     test: /\.(png|jpe?g|gif|svg|webp)$/,
     type: "asset/resource",
   },
 ],
},
plugins: [
 //插件用於增強模塊
 // vue-template-compiler 的作用是解析.vue 文件內部時,遇到js 塊和css 塊時的處理方式,複用我們上面定義的規則
 new VueLoaderPlugin(),
],
}

6. 編寫入口文件 main.js

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

new Vue({
el: "#app",
render: (h) => h(App), //將App 依賴通過渲染函數渲染成DOM 節點,掛載到 #app 節點下
});

<!--App.vue-->
<template>
<div>hello vue starter</div>
</template>
<script>
export default {};
</script>
<style lang="scss" scoped></style>

7. 準備跑起來項目,創建一個快捷腳本去調用非全局webpack 命令

#package.json
"scripts": {
 "serve": "webpack --mode=development --watch", 
 "build": "webpack --mode=production"
},

在package.json 文件中指定的 script 腳本會自動去執行node_modules/bin 下的腳本, mode 選項指定啓動模式:

  • production : 生成環境,壓縮代碼,無錯誤提示
  • development : 開發環境,不壓縮代碼

watch : 檢測文件變化,自動重新編譯打包

8. 啓動項目

cmd 執行命令 npm run serve

dist 目錄下生成了 bundle.js 文件,

此時打開dist 目錄下的index.html 文件。將會看到App.vue 中寫的內容:

image-20211101232725016

這說明初步成功了。

9. 做一些增強,引入路由

安裝依賴

npm i vue-router
# -S 是默認參數

創建 /router/index.js 並編輯:

import VueRouter from "vue-router";
import Home from "../pages/Home.vue";
import Vue from "vue";

Vue.use(VueRouter);

const router = new VueRouter({
routes: [
 {
   path: "",
   component: Home,
 },
 {
   path: "/me",
   component: () => import("../pages/About.vue"),
 },
],
});

export default router;

main.js 中引入:

import Vue from "vue";
import App from "./App.vue";
import router from "./router";

new Vue({
el: "#app",
router,
render: (h) => h(App), //將App 依賴通過渲染函數渲染成DOM 節點,掛載到 #app 節點下
});

App.vue 註冊 <router-view> 標籤:

<template>
<div>
 <span>hello vue starter</span>
 <div><button @click="$router.push('/')">HomePage</button></div>
 <div><button @click="$router.push('/me')">About Me</button></div>
 <router-view></router-view>
</div>
</template>
<script>
export default {};
</script>
<style lang="scss" scoped></style>

啓動程序 npm run serve

image-20211101234624755

10. 進一步增強,引入webpack 開發服務器

```bash
npm i -D webpack-dev-server
```

修改啓動腳本:
pacakge.json

```json
"serve": "webpack --mode=development --watch",
```

修改爲:

```json
"serve": "webpack serve --mode=development",
```

> webpack -dev-server 提供了子命令serve 並會自動watch

配置webpack.config.js

啓動項目:

```bash
npm run serve
```

![image-20211102000024219](https://img2020.cnblogs.com/blog/1735896/202111/1735896-20211102002121545-385713942.png)

![image-20211102000046376](https://img2020.cnblogs.com/blog/1735896/202111/1735896-20211102002121262-958672201.png)

11. 優化配置,自動打開瀏覽器

webpack.config.js:

```json
  devServer: {
    static: "./dist",
    open:true
  },
```

12. 更多

```json
const path = require("path");

const { VueLoaderPlugin } = require("vue-loader");
module.exports = {
  entry: "./src/main.js", //入口文件 絕對路徑 / 相對路徑
  output: {
    //出口文件,
    path: path.resolve(__dirname, "dist") + "", //絕對路徑 __dirname 是node "當前所在路徑pwd" , 由於window 的目錄分隔符是 '\', 而類nix是 '/', 爲了保持靈活性,使用了node 內置的path 對象方法,將自動將當前系統目錄分隔符和目錄名拼接
    filename: "bundle.js",
  },
  module: {
    //webpack 中一切皆模塊
    rules: [
      { test: /\.vue$/, use: "vue-loader" },
      /**
       * 處理.vue 文件的加載, 寫法可以指定
       * 單個依賴 - String,
       * 單個帶配置的依賴 - {}
       * 多個不帶配置的依賴 - []String ,
       * 多個帶配置的依賴 []Object
       * { test: /\.vue$/, use: [{loader:'vue-loader',options:{}},{}...] },
       */
      {
        test: /\.s[ca]ss$/,
        use: ["style-loader", "css-loader", "scss-loader"],
      }, //要注意順序,依次從後往前解析
      {
        test: /\.m?js$/, //.msj 是es6 的模塊化js 文件
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
          },
        },
      },
      {
        //圖片處理
        // test: /\.(png|jpe?g|gif|svg|webp)$/,use: { laoder: "file-loader", options: { esModule: false } },//老語法
        test: /\.(png|jpe?g|gif|svg|webp)$/,
        type: "asset/resource",
      },
    ],
  },
  plugins: [
    //插件用於增強模塊
    // vue-template-compiler 的作用是解析.vue 文件內部時,遇到js 塊和css 塊時的處理方式,複用我們上面定義的規則
    new VueLoaderPlugin(),
  ],
  devServer: {
    static: "./dist",
    open: true,
    host: "local-ip", //啓動地址爲局域網ipv4 地址
    port: 3333, //手動指定地址,
    onListening(devServer) {
      //命令行自定義輸出
      console.log(
        "Listening :http://",
        devServer.server.address().address,
        ":",
        devServer.server.address().port,
      );
    },
  },
};
```
  1. done

  2. https://github.com/jaycethanks/vue-starter

  3. https://www.bilibili.com/video/BV1234y1D7Bv

    https://www.bilibili.com/video/BV1db4y1a7HA

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章