• 从零搭建 vue-cli 脚手架


    前言:

    用了几次 vue-cli 做 vue 项目,感觉没什么大问题,虽然也没有用 vue-router 和 vuex 。但是心里一直有个梗,就是最初的目录生成和配置文件,一直没动过,也不知道具体原理。

    虽然网上一搜,类似对于目录结构的大概介绍也不少,如图:

    1

    仅仅到这一步,估计很多人会心有不甘,而且对于传说中的难以配置的 webpack ,在这里好像也没有什么感觉。实际上,通过在 vue-cli 里写代码,还真是没感觉 webpack 的存在感,,,

    并且尤雨溪也在文章里说明:

    2

    所以我就从头配置了下,在阅读正文前,请确保你有一定的 npm,webpack,vue 基础,下面开始:

    目标:

    通过 vue-cli 配置的项目,如果不加 vue-router 和 测试文件,如图:

    3

    那么生成的项目目录应该是这样子的,顺带看下我的 vue-cli 和 webpack 版本:

    45

    6

    因为版本的不同,安装的时候,如果有错或问题,控制台都会有提示,这个需要随机应变。

    开始:

    1. 在父目录下,新建个文件夹 build-vue-cli-from-zero,切换到 build-vue-cli-from-zero,
    npm init

    按照提示填写:

    7

    主要是 description 建议填写下,否则后面一直会提示,这样项目的第一个文件 package.json 就出现了

    2. 安装相关依赖
    webpack vue vue-loader 这个肯定是要的:
    npm install --save-dev webpack vue vue-loader

    装完后,就会发现 package.json 的内容就多了一些

    8

    这是 --save-dev 的作用,具体不多说了,目录下还多了一个文件:package-lock.json 和文件夹:node_modules

    但是安装完,会发现控制台有警告,这个肯定是要看的,通常有版本更新或者插件停用了,都会有警告的:

    9

    其他的警告仔细看没什么的,但是这两个警告就要求我们还要装依赖了,那么继续装:

    npm install --save-dev css-loader vue-template-compiler

    到这里,控制台还有警告,但是仔细看都无关紧要了:

    10

    所以后面如果还有这些警告,都可以忽略了。

    3. 建立 src 目录

    通常,我们的工作都是在 src 这个目录里完成的,这里我们就仿照 vue-cli 的风格,创建相应的文件和文件夹,当然,这里不如直接复制过来好了

    11

    到这里,乍一看,好像该有的文件都有了,虽然 lint 和 babel 都没装,但是好像也不影响运行,至少能跑起来吧,试试

    npm run dev

    结果报错:

    12

    因为我们到目前为止都没有配置过 webpack ,并不是说装了就可以了,重头戏才刚刚开始

    4. webpack 配置上 - package.json

    在项目下新建 config 文件夹,在里面继续新建 index.js,目前的项目结构如图:

    13

    从事后的角度来说,这里的 index.js 放的就是 webpack 的配置,就像是以前很多人在主文件目录下放的  webpack.config.js 一样,那么配置文件有了,肯定需要有地方运行这个配置文件,你看前面的报错:

    14

    现在再来告诉你配置在 package.json 里:

    "scripts": { "test": "echo "Error: no test specified" && exit 1", "dev": "cross-env NODE_ENV=development webpack-dev-server --config config/index.js" },

    注意,只有 dev 是新加的,test 最初 npm init 的时候就自动生成了,那么这里就要解释下

    cross-env NODE_ENV=development webpack-dev-server --config config/index.js

    1)首先 cross-env webpack-dev-server 都是依赖,这个后面要安装;安装 cross-env 是为了跨平台设置环境变量

    2)NODE_ENV=development 表示设置 NODE 的环境变量为开发环境,这个也好理解

    3)--config config/index.js 表示配置文件在 config/index.js 目录下,当然这里是相对路径,config 必须要和 package.json 在同一个目录,否则要根据情况修改

    到这里,大家应该还想起来了还有个命令 npm run build ,那么以此类推,完整的 scripts 是这样:

    "scripts": { "test": "echo "Error: no test specified" && exit 1", "build": "cross-env NODE_ENV=production webpack --config config/index.js", "dev": "cross-env NODE_ENV=development webpack-dev-server --config config/index.js" }

    前后 build 和 dev 有两点区别,应该有人注意到了,production 和 development 是区分生产和开发环境;

    webpack 和 webpack-dev-server 区别,我觉得是,生产环境下只要打包就行了,而开发环境下需要在 localhost 下测试,所以出现了 dev-server,看名字也很好理解嘛

    这个明白就可以了,那么装依赖:

    npm install --save-dev cross-env webpack-dev-server
    5. webpack 配置下 – index.js

    上面只是好了一半,因为 config/index.js 没有内容嘛,里面要怎么写,看下面:

    //依赖
    const path = require('path'
    )
    const HTMLPlugin 
    = require('html-webpack-plugin')
    //用来生成打包后的 html 文件
    const webpack = require('webpack'
    )
    const extractPlugin 
    = require('extract-text-webpack-plugin')
    //将打包后的 css 从文件中抽出来
    //判断开发或生产环境
    const isDev = process.env.NODE_ENV === 'development'
    //配置文件主体(开发和生产公用的部分)
    const config =
     {
      target: 
    'web'
    ,
      entry: path.join(__dirname, 
    '../src/main.js'
    ),
      output: {
        filename: 
    'bundle.[hash:8].js'
    ,
        path: path.join(__dirname, 
    '../dist/'
    )
      },
      module: {
        //规定文件类型加载的 loader    rules: [
          {
            test: 
    /.vue$/
    ,
            loader: 
    'vue-loader'
    
          },
          {
            test: 
    /.jsx$/
    ,
            loader: 
    'babel-loader'
    
          },
          {
            test: 
    /.(gif|jpg|jpeg|png|svg)$/
    ,
            use: [
              {
                loader: 
    'url-loader'
    ,
                options: {
                  limit: 
    1024
    ,
                  name: 
    '[name]-custom.[ext]'
    
                }
              }
            ]
          }
        ]
      },
      plugins: [
        new webpack.DefinePlugin({
          
    'process.env': { NODE_ENV: isDev ? '"development"' : '"production"'
     }
        }),
        new HTMLPlugin({
          filename: 
    'index.html'
    
        })
      ]
    }
    
    if (isDev) {
      config.mode 
    = 'development'
    
      config.devtool 
    = '#cheap-module-eval-source-map'
    
      config.devServer 
    =
     {
        port: 
    '8080'
    ,
        host: 
    '0.0.0.0',
    //相比 localhost ,可以适用于局域网    overlay: {
          errors: true
        },
        hot: true//热加载  }
      config.plugins.push(
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoEmitOnErrorsPlugin()
      )
      config.module.rules.push(
        {
          test: 
    /.css$/
    ,
          use: [
    'style-loader', 'css-loader'
    ]
        },
        {
          test: 
    /.less$/
    ,
          use: [
            
    'style-loader'
    ,
            
    'css-loader'
    ,
            {
              loader: 
    'postcss-loader'
    ,
              options: { sourceMap: true }
            },
            
    'less-loader'
    
          ]
        }
      )
    } else {
      config.mode 
    = 'production'
    
      config.entry 
    =
     {
        app: path.join(__dirname, 
    '../src/main.js'
    ),
        vendor: [
    'vue'
    ]
      }
      config.output.filename 
    = '[name].[chunkhash:8].js'
    
      config.module.rules.push(
        {
          test: 
    /.css$/
    ,
          use: [
    'style-loader', 'css-loader'
    ]
        },
        {
          test: 
    /.less$/
    ,
          use: extractPlugin.extract({
            fallback: 
    'style-loader'
    ,
            use: [
              
    'css-loader'
    ,
              {
                loader: 
    'postcss-loader'
    ,
                options: { sourceMap: true }
              },
              
    'less-loader'
    
            ]
          })
        }
      )
      config.plugins.push(new
    extractPlugin('styles.[chunkhash:8].css'
    ))
      config.optimization 
    =
     {
        splitChunks: {
          cacheGroups: {
            vendor: {
              name: 
    'vendor'
    
            }
          }
        },
        runtimeChunk: true
      }
    }
    module.exports 
    = config

    这些看不懂很正常,但是要大概理解是干什么的,不能理解的话, webpack 和相关的 loader 和依赖要补补课了;

    根据上面的配置,那么一个个 loader 和依赖就装起来吧

    npm install --save-dev path html-webpack-plugin extract-text-webpack-plugin@next babel-loader url-loader file-loader less-loader style-loader postcss postcss-loader

    上面装完后,会发现:

    15

    那么继续:

    npm install --save-dev babel-core less

    装了 babel 是为了将 ES6 编译成 ES5,自然还要配置下 .babelrc 文件,这个文件要在主目录下新建:

    {
      
    "presets": ["env"], "plugins": ["transform-vue-jsx"] }
    6. 调试

    到这里,好像该装的该配置的都完了,那么我们试试:

    npm run dev

    结果:

    16

    那么继续:

    npm install --save-dev webpack-cli

    结果:

    17

    这个时候再试试 :

    npm run dev

    结果:

    18

    我们把 App.vue 和 main.js 打开,给文件加上后缀名 .vue

    19

    20

    再试试,npm run dev

    21

    根据提示,我们装下:

    npm install --save-dev babel-plugin-transform-vue-jsx

    结果:

    22

    再装下:

    npm install --save-dev babel-helper-vue-jsx-merge-props

    这个时候,没有提示了,再试试,npm run dev

    23

    那么跟之前一样:

    npm install --save-dev babel-plugin-syntax-jsx

    这个时候,也没提示了,继续试试,npm run dev

    24

    那么跟之前一样,

    npm install --save-dev babel-preset-env

    这回终于可以了:

    25

    26

    打开:localhost:8080,F12,刷新下页面

    27

    会发现两个错误,且页面空白

    第一个错误,考虑下也知道了,打开 main.js,给页面加上一个 #app 就可以了

    28

    但是上面的方法,解决不了第二个错误,按照提示给的方法,要么换成 render() 函数,要么用包含编译器的构建;

    这里用 render() 函数来解决,因为后者我不会,- -,也就是把上面截图的代码换成:

    const root = document.createElement('div'
    )
    document.body.appendChild(root)
    new Vue({
      render(h) {
        return h(App)
      }
    }).$mount(root)

    这个时候,再来 npm run dev,一切正常:

    29

    那么好,我们再试试,npm run build

    30

    一切正常,没报错,此时的 dist 和所有文件目录:

    31

    用本地服务器打开,一切正常!

    7. 上传 github,上传之前,文件夹里还要放个文件 .gitignore,里面内容:

    .DS_Store
    node_modules/
    npm-debug.log*
    yarn-debug.log*
    yarn-error.log*
    
    # Editor directories and files
    .idea
    .vscode
    *.suo
    *.ntvs*
    *.njsproj
    *.sln

    这些文件并没有什么用,尤其是 node_modules,同步上去的话,可能有几千甚至上万个文件,不如自己用的时候 npm install 来得方便。

    对比:

    总体实现了之后,我们再来和 vue-cli 的文件目录对比下,左边是 vue-cli,右边是自己实现的:

    32image

    可以发现以下不同:

    1. vue-cli 多了 build 目录

    2. vue-cli 的 config 、dist 结构更清楚,分工更明确

    3. vue-cli 多了 static 可以放静态资源

    4. vue-cli 多了 eslint、postcss 、editor的配置文件和 index.html 模板

    5. vue-cli 引入组件可以省略后缀名

    34

    以及支持模板预编译

    35

    总结:

    1. 与 vue-cli 相比,不足之处还是不少的,如果要补齐,基本上还要修改配置文件,webpack 和各种 loader 的搭配。

    2. 鉴于作者对于 webpack 和 loader 的配置还不够熟悉,只能做到这里,后面的配置等我再仔细学了 webpack 和 loader ,再来补齐。

    最终的项目地址:  build-vue-cli-from-zero

    参考文档:

    Vue.js 目录结构

    新手向:Vue 2.0 的建议学习顺

    Vue+Webpack打造todo应用

    从搭建vue-脚手架到掌握webpack配置(二.插件与提取)

    从零开始搭建一个简单的基于webpack的vue开发环境

    从零开始搭建 webpack + vue + AdminLTE 多页面脚手架

  • 相关阅读:
    对结构化学习(structured learning)的理解
    【语义分割】large kernel matters中GCN模块的pytorch实现
    【C++】使用find函数快速定位元素
    Python通过Openpyxl包汇总表格,效率提升100倍
    conda环境管理
    C++解决大数组问题
    C++ 赋值运算符重载
    [Android] java代码无错误,但跳转失败
    android 如何从activity跳转到另一个activity下指定的fragment
    绝命毒师口语精析(6)
  • 原文地址:https://www.cnblogs.com/xianshenglu/p/8906175.html
Copyright © 2020-2023  润新知