精华内容
下载资源
问答
  • 脚手架这个词估计做前端的都很熟悉。在没有实现前端工程化的年代,前端代码的组织都是纯手工维护的。比如我要做一个网站页面,那么我需要手动创建一个文件夹来存放代码文件,我把它命名为demo。然后在demo目录下创建...

    脚手架这个词估计做前端的都很熟悉。在没有实现前端工程化的年代,前端代码的组织都是纯手工维护的。比如我要做一个网站页面,那么我需要手动创建一个文件夹来存放代码文件,我把它命名为demo。然后在demo目录下创建src文件夹,在src文件夹内创建css文件夹、js文件夹、image文件夹、lib文件夹等等...一切都是手工维护。自从node.js出现后,前端开发才慢慢开始告别刀耕火种,越来越多的自动化工具充斥我们的眼球。模板生成、代码压缩、构建打包、自动部署...这些已经成为构建前端工程项目的标配。那么,一个模板生成的命令行工具的原理是什么?怎样开发一个属于自己的命令行脚手架工具?希望我写的这篇小文章会给大家带来一点启发。

    原理

    生成模板文件的方式可以是本地新建空白文件,然后进行文件内容读写;又或者是把本地已有的模板进行配置信息填充。然而我们知道,IO读写的速度非常慢,性能消耗大。但是一个模板生成器(Generator)如果是基于已有的模板文件进行配置填充,然后在copy到项目目录对应的位置,那会比直接读写磁盘效率更高。所以一般来说,模板生成器会采用第二种工作原理。

    Yeoman-generator

    模板生成器的脚手架有很多,前端领域每天都会有很多类似的轮子源源不断地从开源社区流出。这里我用来开发自己的generator的工具是Yeoman。Yeoman的Logo是一个戴着红帽子的大胡子,它是一个通用的脚手架搭建系统,可以创建任何的类型的app。同时它又是"语言无感知"的,支持创建任何类型开发语言的项目,Web, Java, Python, C# 等等。Yeoman的通用性在于,它本身不做任何决定,所有的操作都是通过Yeoman环境里面的各种generator实现的。通过自定义generator,我们可以创建任何格式的项目目录。这是Yeoman的最大魅力之处。另外,Yeoman通过提供promting这个方法实现输入式命令行交互,可以让用户自由填写配置信息,交互体验也非常棒。下面说说怎样基于Yeoman开发一个简单的generator:



    展开全文
  • 该“ 使用PHP创建交互式生产Wiki ”系列使用PHP从头创建了一个Wiki,其增值功能可用于跟踪生产。 Wiki被广泛用作帮助加快开发速度,提高生产率和教育他人的工具。 该系列的每个部分都将发展Wiki的组成部分,直到它...

    vue脚手架vue数据交互

    存档日期:2019年5月13日 | 首次发布:2007年2月13日

    该“ 使用PHP创建交互式生产Wiki ”系列使用PHP从头创建了一个Wiki,其增值功能可用于跟踪生产。 Wiki被广泛用作帮助加快开发速度,提高生产率和教育他人的工具。 该系列的每个部分都将发展Wiki的组成部分,直到它完成并准备就绪,并具有文件上传,日历“里程碑”系统和开放博客等功能。 Wiki也将包含其权限可自定义为某些用户的项目。

    此内容不再被更新或维护。 全文以PDF格式“按原样”提供。 随着技术的飞速发展,某些内容,步骤或插图可能已更改。

    翻译自: https://www.ibm.com/developerworks/opensource/tutorials/os-php-wiki1/index.html

    vue脚手架vue数据交互

    展开全文
  • vue脚手架vue数据交互Vue.js is a JavaScript library for building user interfaces. Last year, it started to become quite popular among web developers. It’s lightweight, relatively easy to learn, and ...

    vue脚手架vue数据交互

    Vue.js is a JavaScript library for building user interfaces. Last year, it started to become quite popular among web developers. It’s lightweight, relatively easy to learn, and powerful.

    Vue.js是用于构建用户界面JavaScript库。 去年,它开始在Web开发人员中变得非常流行。 它轻巧,易于学习且功能强大。

    In the three minutes that Medium says it will take you to read this article, you’ll be equipped to start building basic Vue apps. With each segment, I’ve also included an interactive Scrimba screencast, where you can watch me explain the concepts and play around with the code yourself.

    在Medium说的三分钟内,您将需要阅读本文,您将具备开始构建基本的Vue应用程序的能力。 在每个部分中,我还包括一个互动式Scrimba截屏,您可以在其中观看我讲解概念并亲自使用代码。

    Let’s jump into it.

    让我们跳进去。

    模板语法和数据 (Template syntax and data)

    At the core of Vue.js is a straightforward template syntax which looks like this:

    Vue.js的核心是简单的模板语法,如下所示:

    <div id="myApp">  
        {{ message }}  
    </div>

    Pair that with the following JavaScript snippet:

    将其与以下JavaScript代码段配对:

    var myApp = new Vue({  
       el: '#myApp',  
       data: {  
           message: 'Hello world!'  
       }  
    })

    And it’ll result in Hello world! being rendered on the page.

    它将进入Hello World! 在页面上呈现。

    The el: #myApp part tells Vue to render the app inside the DOM element with the id of myApp. The data object is where you place you the data you want to use in your app. We’ve added only one key here, message, which we’re referencing to in our HTML like this: {{ message }}.

    el: #myApp部分告诉Vue使用myApp的ID在DOM元素内渲染应用程序 data对象是放置要在应用程序中使用的数据的位置。 我们在此处仅添加了一个键message ,它在我们HTML中是这样引用的: {{ message }}

    Vue takes care of linking the data object to the DOM, so if the data changes, the page will be updated as well.

    Vue负责将data对象链接到DOM,因此,如果数据发生更改,页面也将被更新。

    This is called declarative rendering. You simply specify what you want to update, and Vue takes care of how to do it.

    这称为声明式渲染。 您只需指定要更新什么 ,Vue公司需要照顾怎么办呢。

    You can change the data can by doing this:

    您可以通过执行以下操作来更改数据罐:

    myApp.message = 'Some new value';

    Here is a screencast which explains this exact concept:

    这是一个截屏视频,解释了这个确切的概念:

    指令 (Directives)

    The next concept you’ll need to learn is directives. Directives are HTML attributes that are prefixed with v-, which indicates that they apply reactive behavior to the rendered DOM.

    您需要学习的下一个概念是指令。 指令是带有v-前缀HTML属性,指示它们将React式行为应用于呈现的DOM。

    Let’s say we only want to render something if a condition is true, and hide it if it’s false. Then we’ll use v-if.

    假设我们只想在条件为true时渲染某些内容,而在条件为false时隐藏它。 然后,我们将使用v-if

    In the HTML, it looks like this.

    在HTML中,它看起来像这样。

    <div id="app">  
        <p v-if="seen">Now you see me</p>  
    </div>

    And some JavaScript:

    还有一些JavaScript:

    var app = new Vue({  
        el: '#app',  
        data: {  
            seen: true  
        }  
    })

    This will result in rendering out the Now you see me paragraph if seen in data is true. To hide the paragraph, you can set seen to false, like this:

    如果在data seen的是真实的,这将导致呈现“ 立即看到我”段落 要隐藏该段落,可以将seen设置为false,如下所示:

    app.seen = false;

    app.seen = false;

    Here is a screencast explaining the same concept:

    这是解释相同概念的截屏视频:

    There are many other directives, like v-for, v-on, v-bind and v-model.

    还有许多其他指令,例如v-forv-on, v-bindv-model

    处理用户输入 (Handling user input)

    Another core directive you need to learn is v-on. It will hook up an event listener to the DOM element, so that you can handle user input. You specify the type of event after the colon. So v-on:click will listen for clicks.

    您需要学习的另一个核心指令是v-on 。 它将事件监听器连接到DOM元素,以便您可以处理用户输入。 您可以在冒号后面指定事件的类型。 因此, v-on:click将监听点击。

    <div id="app">  
        <button v-on:click="myClickHandler">Click me!</button>  
    </div>

    myClickHandler refers to the key with the same name in the methods object. Needless to say, that’s the object where you place your app’s methods. You can have as many methods as you want.

    myClickHandlermethods对象中引用具有相同名称的键。 不用说,这就是放置应用程序方法的对象。 您可以根据需要使用多种方法。

    var app = new Vue({  
        el: '#app',  
        methods: {  
            myClickHandler: function () {  
                console.log('button clicked!');  
            }  
        }  
    })

    This will result in button clicked being logged to the console when clicking the button.

    这将导致按钮单击单击按钮时被记录到控制台。

    Here is a screencast explaining the concept:

    这是解释此概念的截屏视频:

    绑在一起 (Tying it all together)

    Now let’s create an example where we’re using both data and methods, tying together what we’ve learned up until now.

    现在,让我们创建一个示例,在此示例中,我们同时使用datamethods ,将到目前为止所学的知识联系在一起。

    <div id="app">  
        <p>{{ message }}</p>  
        <button v-on:click="changeMessage">Click me!</button>  
    </div>

    And the JavaScript:

    和JavaScript:

    var app = new Vue({  
        el: '#app',  
        data: {  
            message: 'Start message'  
        },  
        methods: {  
            changeMessage: function () {  
                this.message = 'The message has changed!'  
            }  
        }  
    })

    Initially, it’ll display out Start message on the page, however after the click it’ll display This message has changed instead.

    最初,它将在页面上显示开始消息 ,但是单击后将显示此消息已更改

    The this  keyword refers to the Vue instance, the one we’ve called app. It is on this instance that our data lives, so we can refer to the message data through this.message.

    this关键字引用Vue实例,我们将其称为app 。 正是在这种情况下,我们的数据才得以生存,因此我们可以通过this.message引用message数据。

    Check out this screencast explaining the concept.

    查看此截屏视频,以解释概念。

    And by that, you should know enough Vue.js to get started creating simple apps.

    这样一来,您应该了解足够的Vue.js才能开始创建简单的应用程序。

    In the next tutorial, you’ll learn how to create Vue components. So be sure to follow this publication if you liked this article.

    在下一个教程中,您将学习如何创建Vue组件。 因此,如果您喜欢本文,请确保遵循该出版物。

    翻译自: https://www.freecodecamp.org/news/learn-basic-vue-js-crash-course-guide-vue-tutorial-e3da361c635/

    vue脚手架vue数据交互

    展开全文
  • 本文记录我从开源一个Vue组件出发,到模板以及脚手架开发,最终开源了一套脚手架工具的过程 背景 在流水的前端开发的工作中,难免遇到需要依靠一些开源的库,但这些库有时又不能满足我的需求,差之毫厘谬以千里。...


    本文记录我从开源一个Vue组件出发,到模板以及脚手架开发,最终开源了一套脚手架工具的过程

    背景

    在流水式的前端开发的工作中,难免遇到需要依靠一些开源的库,但这些库有时又不能满足我的需求,差之毫厘谬以千里。于是我萌生了一个想法:为什么我不能开源一个项目、一个库、一个组件呢?

    需要解决的问题

    • Vue组件开发
      • 支持全局注册
      • 开发流程
    • npm
      • 发布
      • 版本控制
      • 发布流程
    • webpack 搭建
      • 本地调试
      • 打包
      • 常用配置项的理解
      • 优化的配置项
    • 组件开发模板
      • 易懂的README
    • 脚手架
      • 易懂的README
      • 更简单的命令行

    Vue组件开发

    出发点是需要一个Vue组件,那我们首先来看看如何开发一个Vue组件

    核心代码

    阅读Vue官方文档,可以在插件处看到Vue组件的开发方式:

    Vue.js 的插件应该有一个公开方法 install。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:

    MyPlugin.install = function (Vue, options) {
      // 1. 添加全局方法或属性
      Vue.myGlobalMethod = function () {
        // 逻辑...
      }
    
      // 2. 添加全局资源
      Vue.directive('my-directive', {
        bind (el, binding, vnode, oldVnode) {
          // 逻辑...
        }
        ...
      })
    
      // 3. 注入组件
      Vue.mixin({
        created: function () {
          // 逻辑...
        }
        ...
      })
    
      // 4. 添加实例方法
      Vue.prototype.$myMethod = function (methodOptions) {
        // 逻辑...
      }
    }
    

    通过全局方法 Vue.use() 使用插件。它需要在你调用 new Vue() 启动应用之前完成:

    // 调用 `MyPlugin.install(Vue)`
    Vue.use(MyPlugin)
    
    new Vue({
      //... options
    })
    

    着手开发一个Vue组件

    新建一个空文件夹作为组件项目空间,并初始化package.json

    mkdir vue-hello
    cd vue-hello
    npm init
    

    按照提示输入相关信息(之后可修改)
    接着构造以下目录:

    |——src // 组件源码
    |   |——common // 通用文件,如全局css,utils
    |   |——components // 组件路径,每个文件夹对应一个组件
    |   |   |——hello
    |   |   |   |——index.vue
    |   |   |   |--index.css 对应组件的样式代码
    |   |——index.js // 组件打包入口
    |——package.json
    |——webpack.config.js // 打包配置文件
    

    在hello/index.vue中写入代码:

    <template>
        <div>hello world</div>
    </template>
    <script>
        export default {
            name: 'hello'
        }
    </script>
    

    在src/index.js中写入代码:

    import Hello from './components/hello/index.vue'
    
    const install = function (Vue) {
        if (install.installed) {
            return
        }
        Vue.component(Hello.name, Hello) // 注册全局component
    }
    // 支持标签引入
    if (typeof window !== 'undefined' && window.Vue) {
        install(window.Vue)
    }
    
    export default {
        install,  // 引入时Vue.use()方法执行这个install方法
        Hello
    }
    

    由于vue-cli中有许多优化的配置项我们暂时不需要,在这里我们选择自己搭建一个webpack配置文件:

    const path = require('path'); // 路径处理模块
    const {
        VueLoaderPlugin
    } = require('vue-loader');
    
    module.exports = {
        entry: {
            index: path.join(__dirname, "/src/index.js") // 入口
        },
        output: {
            path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
            publicPath: '/dist/', // 设置公共路径
            filename: "bundle.js", // 打包后输出文件的文件名
            libraryTarget: 'umd' // 将你的library暴露为所有的模块定义下都可运行的方式,它将可在 CommonJS, AMD 环境下运行
        },
        module: {
            rules: [{
                    test: /\.js$/,
                    use: 'babel-loader', // 解析js
                    exclude: /node_modules/
                },
                {
                    test: /\.(png|svg|jpg|gif)$/,
                    use: [
                        'file-loader' // 解析图片文件
                    ]
                },
                {
                    test: /\.(woff|woff2|eot|ttf|otf)$/,
                    use: [
                        'file-loader' // 解析文字文件
                    ]
                },
                {
                    test: /\.vue$/,
                    loader: 'vue-loader' // 解析vue
                },
                {
                    test: /\.css$/,
                    use: ['vue-style-loader', 'css-loader'] // 解析vue
                }
            ]
        },
        plugins: [
            new VueLoaderPlugin() // 解析.vue文件
        ]
    }
    

    关于webpack配置我将在后面详细描述,这里先关注需要用到的依赖,在package.json中写入依赖:

     "devDependencies": {
        "babel-core": "^6.26.3",
        "babel-loader": "^7.1.5",
        "babel-preset-env": "^1.7.0",
        "css-loader": "^1.0.0",
        "file-loader": "^2.0.0",
        "style-loader": "^0.23.1",
        "url-loader": "^1.1.2",
        "vue": "^2.5.17",
        "vue-hot-reload-api": "^2.2.4",
        "vue-html-loader": "^1.2.4",
        "vue-loader": "^15.4.2",
        "vue-router": "^3.0.1",
        "vue-style-loader": "^3.0.3",
        "vue-template-compiler": "^2.5.9",
        "webpack": "^4.23.1",
        "webpack-cli": "^3.1.2"
      }
    

    安装依赖

    npm install -D
    

    最后在package.json中写入打包指令:

    "scripts": {
        "build": "webpack --mode production"
      },
    

    然后执行npm run build即可在根目录下生成一个dist目录,里面的bundle.js就是我们的hello组件啦

    在发布npm包之前,我们可以本地测试一下这个组件,在src目录下新建dev.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <script src="../node_modules/vue/dist/vue.js"></script>
        <script src="../dist/bundle.js"></script>
        <div id="app">
            <hello></hello>
        </div>
        <script>
            new Vue({
                el: '#app'
            })
        </script>
    </body>
    </html>
    

    没有问题的话,在浏览器中就可以看到熟悉的hello world了!

    发布npm包

    发布npm包前我们需要修改package.json文件的部分内容:

    {
      "name": "vue-hello",  // 包名称,默认和你文件夹同名,可改,但是需要去npm官网搜素这个名称是否已存在,因为包名不能重复
      "version": "1.0.0",  // 项目默认版本号,可改,如果项目后期更新再发布,则需要修改版本号
      "description": "",   // 项目描述,选填,可利于SEO 
      "main": "dist/bundle.js",  // 你的包的主要入口路径,就是别人安装了你的包后系统会去这个路径找你的代码
      "scripts": {         
        "build": "webpack --mode production"
      },
      "author": "",        // 作者,选填
      "license": "ISC"     // 许可证,默认即可
    }
    

    然后执行npm login登录&npm publish即可发布,如果发布失败可能是权限问题,macos用户可执行sudo npm publish

    完整的Vue组件开发模板

    为了方便组件开发者进行本地调试,我们需要完善webpack配置,并优化项目结构,达到以下目的:

    • 开发者只需使用该模板就能直接进行组件开发,无需关注其他配置
    • 提供模板依赖的脚手架,一个命令生成模板
    • 完整易读的README,快速上手

    那么赶紧开始吧!

    修改目录结构

    首先修改项目名称为vc-component,意为vue通用(common)组件(component)开发模板(template)

    |——build // webpack配置文件目录
    |   |——build.js // node打包脚本入口
    |   |——webpack.base.conf.js // 通用的webpack配置
    |   |——webpack.dev.conf.js // 本地调试的webpack配置
    |   |——webpack.prod.conf.js // 打包时的webpack配置
    |——src // 组件源码
    |   |——common // 通用文件
    |   |   |——common.less  // 全局样式,选择使用less
    |   |——components // 组件路径,每个文件夹代表一个组件
    |   |   |——hello
    |   |   |   |——index.vue
    |   |   |   |——index.less
    |   |   |——dev.html // 本地html调试
    |   |   |——index.js // 组件打包入口
    |   |——App.vue // vue根元素
    |   |——index.js // devserver的入口文件
    |——.babelrc // babel配置文件
    |——.gitignore // git同步代码时忽略的部分
    |——.npmignore // npm同步代码时忽略的部分
    |——index.html // vue挂载的根元素
    |——package.json // 项目信息
    |——README.md // 使用说明
    

    build

    • webpack.base.conf.js
      该文件主要配置了通用webpack,包括常用的loader解析,postcss,通用插件HtmlWebpackPlugin等。由于dev出入口和build出入欧不同,将分开配置。
    module.exports = {
      resolve: {
        alias: {
          'vue$': 'vue/dist/vue.esm.js', // vue ES module版本,使webpack可以找到vue文件
          '@': path.resolve(__dirname, '../src'), // 解析@为src目录
        },
        extensions: ['*', '.js', '.json', '.vue'] // import可省略后缀
      },
      module: {
        rules: [{
            test: /\.js$/,
            use: 'babel-loader', // 解析js
            exclude: /node_modules/
          },
          {
            test: /\.(png|svg|jpg|gif)$/,
            use: [
              'file-loader' // 解析图片文件
            ]
          },
          {
            test: /\.(woff|woff2|eot|ttf|otf)$/,
            use: [
              'file-loader' // 解析文字文件
            ]
          },
          {
            test: /\.vue$/,
            loader: 'vue-loader' // 解析vue
          },
          {
            test: /\.css$/,
            use: ['vue-style-loader', 'css-loader', 'postcss-loader'] // 解析css文件,postcss后处理器
          },
          {
            test: /\.less$/,
            use: ['vue-style-loader', 'css-loader', 'postcss-loader', 'less-loader'] // 解析less文件
          }
        ]
      },
      plugins: [
        new VueLoaderPlugin(),  // 也是为了解析vue
        new HtmlWebpackPlugin({ // 将打包产生的文件挂载到目标html上
          template: path.resolve(__dirname, '../index.html')
        })
      ]
    };
    
    • webpack.dev.conf.js
      配置了dev环境下的webpack,dev下的入口为src/index.js,与传统vue-cli相同,启动了一个devserver,同时开启了模块热更新,优化了complier信息等。
    const devWebpackConfig = merge(baseConfig, {
      mode: 'development',
      devtool: 'inline-source-map',
      entry: {
        bundle: path.resolve(__dirname, '../src/index.js')
      },
      output: {
        path: path.resolve(__dirname, '../dev-dist'),
        filename: '[name].[hash].js'
      },
      module: {
        rules: [{
            test: /\.css$/,
            use: ['vue-style-loader', 'css-loader', 'postcss-loader'] // 解析css文件,postcss后处理器,需要在根目录下新建postcss.config.js
          },
          {
            test: /\.less$/,
            use: ['vue-style-loader', 'css-loader', 'postcss-loader', 'less-loader'] // 解析less文件
          }
        ]
      },
      plugins: [
        new webpack.HotModuleReplacementPlugin(), // 模块热更新
        
      ],
      devServer: {
        contentBase: path.resolve(__dirname, '../dev-dist'),
        open: false, // 禁止自动开启浏览器
        hot: true, // 开启模块热更新
        clientLogLevel: "none", // 不在浏览器控制台打印
        quiet: true, // 配合FriendlyErrorsPlugin使用
        host: 'localhost',
        port: 8080
      },
    });
    
    module.exports = new Promise((resolve, reject) => {
      portfinder.basePort = process.env.PORT || 8080
      portfinder.getPort((err, port) => {
        if(err) {
          reject(err)
        } else {
          devWebpackConfig.devServer.port = port // 端口自增
          devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({  // 优化compiler信息
            compilationSuccessInfo: {
              messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
            },
          }))
          resolve(devWebpackConfig)
        }
      })
    })
    
    • webpack.prod.conf.js
      配置了build时的webpack
    const merge = require('webpack-merge');
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    const path = require('path');
    const baseConfig = require('./webpack.base.conf');
    module.exports = merge(baseConfig, {
      mode: 'production',
      devtool: 'source-map',
      entry: {
        bundle: path.resolve(__dirname, '../src/components/index.js')
      },
      output: {
        path: path.resolve(__dirname, '../dist'),
        filename: 'bundle.js'
      },
      module: {
        rules: [
        ]
      },
      plugins: [
        new CleanWebpackPlugin(['dist/'], {
          root: path.resolve(__dirname, '../'),
          verbose: true,
          dry: false
        }),
      ]
    });
    
    • 看一下此时的package.json
    {
      "name": "vc-component",
      "version": "1.0.0",
      "description": "a component template for vue",
      "main": "dist/bundle.js",
      "scripts": {
        "build": "node build/build.js",
        "dev": "webpack-dev-server --progress --config build/webpack.dev.conf.js"
      },
      "repository": {
        "type": "git",
        "url": "git+https://github.com/1465799166/vc-component.git"
      },
      "keywords": [
        "vue",
        "component"
      ],
      "author": "shenjiaheng",
      "license": "ISC",
      "bugs": {
        "url": "https://github.com/1465799166/vc-component/issues"
      },
      "homepage": "https://github.com/1465799166/vc-component#readme",
      "devDependencies": {
        "babel-core": "^6.26.3",
        "babel-loader": "^7.1.5",
        "babel-preset-env": "^1.7.0",
        "clean-webpack-plugin": "^1.0.1",
        "css-loader": "^1.0.0",
        "file-loader": "^2.0.0",
        "friendly-errors-webpack-plugin": "^1.7.0",
        "html-webpack-plugin": "^3.2.0",
        "less": "^3.9.0",
        "less-loader": "^4.1.0",
        "mini-css-extract-plugin": "^0.5.0",
        "portfinder": "^1.0.20",
        "postcss-cssnext": "^3.1.0",
        "postcss-loader": "^3.0.0",
        "style-loader": "^0.23.1",
        "url-loader": "^1.1.2",
        "vue-hot-reload-api": "^2.2.4",
        "vue-html-loader": "^1.2.4",
        "vue-loader": "^15.4.2",
        "vue-style-loader": "^3.0.3",
        "vue-template-compiler": "^2.5.9",
        "webpack": "^4.23.1",
        "webpack-cli": "^3.1.2",
        "webpack-dev-server": "^3.1.14",
        "webpack-merge": "^4.2.1"
      },
      "dependencies": {
        "vue": "^2.5.22",
        "vue-router": "^3.0.2"
      }
    }
    
    

    至此webpack配置就完成了,但是这个配置仍有很多不足之处有待完善,接下来编写README就不多说了,大家自行操作。

    贴一下项目地址,欢迎star

    TODO:

    • 优化打包体积
    • 优化编译速度
    • 压缩js代码
    • 提取css文件
    • 优化build时命令行输出

    脚手架

    该脚手架的目的是为了能够更方便的使用上述模板,今后的开发将不再关注脚手架代码,模板代码。

    技术选择

    我选择了这几个库来搭建我的脚手架:

    • commander 用于解析命令,并执行相关操作
    • inquirer 优化命令行交互,用更多的选择操作来替代输入操作
    • ora 提供命令操作后的loading
    • chalk 美化命令行文字

    package.json中加入:

    "dependencies": {
        "chalk": "^1.1.3",
        "commander": "^2.9.0",
        "inquirer": "^6.2.1",
        "ora": "^3.0.0"
    }
    

    然后执行npm install

    实现方案

    该脚手架需要实现基于模板的项目初始化,模板删除,模板添加,模板列表展示,具体实现如下:

    构造如下目录:

    |——bin
    |   |——vs // 命令入口
    |——command // 命令执行文件
    |   |——add.js
    |   |——delete.js
    |   |——init.js
    |   |——list.js
    |——.gitignore
    |——.npmignore
    |——package.json
    |——README.md
    |——templates.json // 模板存放
    

    在bin/vs中实现4个命令:

    #!/usr/bin/env node
    
    'use strict'
    
    process.env.NODE_PATH = __dirname + '/../node_modules/'
    
    const program = require('commander')
    
    program
    	.version(require('../package').version )
    
    program
    	.usage('<command>')
    
    program
    	.command('add')
    	.description('Add a new template')
      .alias('a')
      .action(() => {
        require('../command/add')()
      })
    
    program
    	.command('list')
    	.description('List all the templates')
    	.alias('l')
    	.action(() => {
    		require('../command/list')()
    	})
    
    program
    	.command('init')
    	.description('Generate a new project')
      .alias('i')
      .action(() => {
        require('../command/init')()
      })
    
    program
    	.command('delete')
    	.description('Delete a template')
    	.alias('d')
    	.action(() => {
    		require('../command/delete')()
    	})
    
    program.parse(process.argv)
    
    if(!program.args.length){
      program.help()
    }
    

    然后在command下实现这4个命令相应的执行内容:

    // add.js
    'use strict'
    const config = require('../templates')
    const fs = require('fs')
    const inquirer = require('inquirer')
    const ora = require('ora');
    
    module.exports = () => {
      inquirer.prompt([{
          type: 'input',
          message: '模板名称: ',
          name: 'name',
          validate(val) {
            if (config.tpl[val]) {
              return '模板名已存在!'
            }
            return true
          }
        },
        {
          type: 'input',
          message: '模板Git仓库地址: ',
          name: 'git'
        },
        {
          type: 'input',
          message: '模板分支: ',
          name: 'branch'
        },
        {
          type: 'input',
          message: '描述(可省略): ',
          name: 'description'
        }
      ]).then(tpl => {
        const spinner = ora('模板添加中...').start()
        config.tpl[tpl.name] = {
          tplName: tpl.name,
          url: tpl.git.replace(/[\u0000-\u0019]/g, ''), // 过滤unicode字符
          branch: tpl.branch,
          description: tpl.description
        }
        fs.writeFile(__dirname + '/../templates.json', JSON.stringify(config), 'utf-8', (err) => {
          if (err) spinner.fail('模板添加失败!')
          spinner.succeed('模板添加成功')
          process.exit()
        })
      })
    }
    
    // delete.js
    'use strict'
    const config = require('../templates')
    const fs = require('fs')
    const inquirer = require('inquirer')
    const ora = require('ora')
    module.exports = () => {
        let tplList = []
        for (let i in config.tpl) {
          tplList.push(i)
        }
        inquirer.prompt([
            {
                type: 'list',
                name: 'template',
                message: '请选择要删除的模板',
                choices: tplList
            }
        ]).then(res => {
            let tplName = res.template
            let spinner = ora()
            if (config.tpl[tplName]) {
                config.tpl[tplName] = undefined
            } else {
                spinner.fail('模板不存在!')
                process.exit()
            }
            fs.writeFile(__dirname + '/../templates.json', JSON.stringify(config),  'utf-8', (err) => {
                if (err) {
                    console.log(err)
                    spinner.fail('删除失败')
                    process.exit()
                }
                spinner.succeed('删除成功')
                process.exit()
            })
        })
    }
    
    // init.js
    'use strict'
    const exec = require('child_process').exec
    const config = require('../templates')
    const chalk = require('chalk')
    const inquirer = require('inquirer')
    const ora = require('ora')
    module.exports = () => {
        let tplList = []
        for (let i in config.tpl) {
          tplList.push(i)
        }
        inquirer.prompt([{
          type: 'list',
          name: 'templates',
          message: '请选择初始化模板:',
          choices: tplList
        }]).then(res => {
          const spinner = ora('模板下载中...').start()
          let gitUrl = config.tpl[res.templates].url
          let branch = config.tpl[res.templates].branch
          let cmdStr = `git clone ${gitUrl} . && git checkout ${branch}`
          exec(cmdStr, (error, stdout, stderr) => {
            if (error && error.code == 128) {
              spinner.fail('请在空目录中初始化!')
              process.exit()
            }
            if (error) {
              console.log(stderr)
              spinner.fail('模板下载失败!')
              process.exit()
            }
            spinner.succeed('模板下载成功!')
            process.exit()
          })
        })
    
    }
    
    // list.js
    'use strict'
    const config = require('../templates')
    const chalk = require('chalk')
    module.exports = () => {
    	 for (let i in config.tpl) {
    		 console.info(`${chalk.green(i)}——${chalk.yellow(config.tpl[i].description)}`)
    	 }
     	process.exit()
    }
    

    然后初始化templates.json:

    {
        "tpl": {}
    }
    

    最后修改package.json中的bin属性,使得我们的vs文件作为脚手架的入口:

    "bin": {
        "vs": "bin/vs"
    },
    

    这样脚手架的代码就实现了,然后我们可以执行npm link(如果失败可能是没有权限,自行解决吧),即可把vs命令注册到全局了。

    发布脚手架

    其实就是发布npm包了:

    npm publish
    

    使用的话需要全局安装,这样才有脚手架的样子:

    npm install vs-sarffold -g
    

    这里贴一下完整源码,需要的可以看下

    结束语

    起点只是为了开发一个vue组件,没想到这一路牵扯到了这么多知识点,可以说收获颇深了,所以说还是生命不息,学习不止啊。

    展开全文
  • 构建脚手架命令行工具 我们这一章节呢,来总结下构建脚手架的基本过程,总的来说呢,过程也是相当愉快轻松的,愉快,心情完美 ~ 安装依赖 首先我们需要安装构建脚手架所需要的依赖,如下: cnpm install -D ...
  • web前端开发之vue脚手架

    千次阅读 2021-03-11 13:14:25
    通过 @vue/cli 实现的交互式的项目脚手架。 通过 @vue/cli + @vue/cli-service-global 实现的零配置原型开发。 一、安装和配置脚手架 1.1 安装脚手架 npm install -g @vue/cli // -g是全局安装 1.2 创建一个项目 ...
  • StoryBook 是一套 UI 组件的开发环境,它允许你浏览组件库,查看每个组件的不同状态,以及交互式开发和测试组件。 Lerna 帮你管理你的包集合,当你自己的 library 变多时,你的版本控制,跟踪管理,测试就会变得越发...
  • 持续更新。。。 Commander.js ...常见的交互式命令行用户界面的集合 安装:npm install inquirer npm地址:https://www.npmjs.com/package/inquirer execa 描述:执行命令包 安装:npm install execa
  • 通过 mix-go/mixcli 实现的交互式项目脚手架: 可以生成 cli, api, web, grpc 多种项目代码 生成的代码开箱即用 可选择是否需要 .env 环境配置 可选择是否需要 .yml, .json, .toml 等独立配置 可选择使用 gorm, ...
  • 基于交互式命令行的方式(cmd)

    千次阅读 2020-05-29 15:22:03
    Vue-cli的安装搭建- -基于交互式命令行的方式 基于交互式命令行的方式(cmd),搭建新版vue项目。 cmd中运行vue create 项目名 1. 选择安装配置方式 default (babel, eslint) ->默认 Manually select ...
  • Vue脚手架

    2020-10-19 21:03:06
    文章目录前言一、脚手架开发1、介绍2、该系统的组件3、CLI4、...通过 @vue/cli 实现的交互式的项目脚手架。 通过 @vue/cli + @vue/cli-service-global 实现的零配置原型开发。 一个运行时依赖 (@vue/cli-service),该.
  • 一、前端工程化 概念:遵循一定的标准和规范,通过工具去提高效率,降低...多人协同开发,无法硬性统一大家的代码风格,从仓库中pull回来的代码质量无法保证 2、主要解决的问题 传统语言或语法的弊端,无法使用模
  • 5.重复的机械工作 6.整体依赖后端项目 脚手架工具概要 1.创建项目基础结构、提供项目规范和约定 相同的组织结构 相同的开发范式 相同的模块依赖 相同的工具配置 相同的基础代码 2.常用脚手架工具 react项目:...
  • 内容提要:提供开始构建新闻应用程序或交互式图形所需的一切。 安装 在开始之前,您需要安装以下组件: NodeJS / NPM Grunt命令行实用程序(grunt-cli,全局安装) Grunt项目脚手架(grunt-init,已全局安装) ...
  • vue脚手架

    2021-03-11 14:10:51
    文章目录一、vue脚手架使用二、安装脚手架...通过 @vue/cli 实现的交互式的项目脚手架。 通过 @vue/cli + @vue/cli-service-global 实现的零配置原型开发。 Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了.
  • 结果 脚手架的工作原理 • 就是问点问题, 根据问题定制如何将模板文件复制渲染出来 案例: 实现一个基础的脚手架 • 问问题 + 复制模板 NodeJs 交互式命令行工具 提供错误回调 询问操作者问题 获取并解析用户输入 ...
  • 开发脚手架与自动化构建工作流封装 去年6月24号开始工作,到今天刚好一周年了,纪念一下,分享最近学习的前端工程化笔记。 一、前端工程化 前端工程化是指遵循一定的标准和规范,通过工具去提高效率、降低成本的一种...
  • 文章目录一、ptm-cli 使用说明1、特点2、安装3、使用1)基础帮助命令2)添加模板/项目3)编辑模板/项目4)查看模板/项目5)删除模板/项目6)基于模板新建/初始化项目二 `ptm-cli` 脚手架开发1、知识储备1)commander...
  • 一、脚手架(vue-cli) 1.Vue 脚手架的基本用法 Vue 脚手架用于快速生成 Vue 项目... 基于 交互式命令行 的方式,创建 新版 vue 项目 vue create my-project // 2. 基于 图形化界面 的方式,创建 新版 vue 项目...
  • 序为什么要自己搭建项目 ?这个事情起始于前两天给团队写一个脚手架工具,这段时间刚做做完一个系统,是团队第一个正式意义上的全栈项目;...前两天用 JavaScript 完成了脚手架的初版,开发过程中发现没一点...
  • 引言下面是一个使用脚手架来初始化项目的典型例子。随着前端工程化的理念不断深入,越来越多的人选择使用脚手架来从零到一搭建自己的项目。其中大家最熟悉的就是create-react-app和v...
  • 使用Facebook的create-react-app脚手架快速构建React开发环境(ant.design,redux......) 编程领域中的“脚手架(Scaffolding)”指的是能够快速搭建项目“骨架”的一类工具。例如大多数的React项目都有src,...
  • swagger2在线可调接口 有了 swagger,开发人员不需要给其他人员提供接口文档,只要告诉他们一个 Swagger 地址,即可展示在线的 API 接口文档,除此之外,调用接口的人员还可以在线测试接口数据,同样地,开发人员...
  • 首先安装脚手架及创建基于webpack项目 首先下载vue相关 cnpm install vue 安装 vue-cli脚手架 全局安装 vue-cli $ cnpm install –global vue-cli 创建一个基于 webpack 模板的新项目 $ vue init webpack my-...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,329
精华内容 1,731
关键字:

交互式脚手架开发