<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Brian Winkers</title>
    <description>The latest articles on DEV Community by Brian Winkers (@bwinkers).</description>
    <link>https://dev.to/bwinkers</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F539146%2F6f35254d-465a-4fc2-823b-d838722e55f5.jpeg</url>
      <title>DEV Community: Brian Winkers</title>
      <link>https://dev.to/bwinkers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bwinkers"/>
    <language>en</language>
    <item>
      <title>Developing and packaging Vue components using NPM</title>
      <dc:creator>Brian Winkers</dc:creator>
      <pubDate>Tue, 27 Apr 2021 07:17:09 +0000</pubDate>
      <link>https://dev.to/bwinkers/developing-and-packaging-vue-components-using-npm-3bgo</link>
      <guid>https://dev.to/bwinkers/developing-and-packaging-vue-components-using-npm-3bgo</guid>
      <description>&lt;p&gt;This article provides some tips from my recent real-world experience with developing and packaging the &lt;a href="https://github.com/bwinkers/multicorder"&gt;Multicorder&lt;/a&gt; as an &lt;a href="https://www.npmjs.com/package/multicorder"&gt;NPM&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal
&lt;/h2&gt;

&lt;p&gt;My goal was to publish a fully styled UI component. I accomplished that but learned a lot along the way. My goals changed somewhat as the weekend progressed. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why publish NPM's?
&lt;/h3&gt;

&lt;p&gt;I'm a firm believer in separating logic out into packages, no matter what the language. They don't necessarily need to be published on public repositories. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Problems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;p&gt;I came to understand that including relatively heavy dependencies like Vuetify as the sole artifact in an NPM wasn't a best practice.&lt;/p&gt;

&lt;p&gt;I ended up with all the logic in a Vue 2 file with no dependencies. Furthermore, I also publish a Vuetify component that uses the base module and wraps it in some straight forward interface logic.&lt;/p&gt;

&lt;p&gt;This gives me the best of all worlds. I have a fully functional UI component that will fit right in with any Vue2/Vuetify app I create. If I run into a situation where that UI component won't work I can easily call the same functionality from other UI components, I could even build a UI in MDB Bootstrap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the Code Locally
&lt;/h3&gt;

&lt;p&gt;I'm very adept at testing software and have written many NPM using &lt;code&gt;npm link&lt;/code&gt; to test the package locally. So I figured this would be the easy part, I was wrong. I guess the &lt;code&gt;vue-loader&lt;/code&gt; has issues with &lt;code&gt;npm link&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I was able to find a solution using &lt;code&gt;npm pack&lt;/code&gt;. It's a bit cumbersome, but I can add automation later. It provides completely accurate testing of how the &lt;code&gt;npm&lt;/code&gt; will behave and that is the key.&lt;/p&gt;

&lt;p&gt;That solution doesn't support hot reloading so yet another paradigm was needed for iterative development. For that we load the Vue component directly from within a Vuetify app. The &lt;code&gt;vuetify_ui&lt;/code&gt; code is used for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use vue-sfc-rollup&lt;/li&gt;
&lt;li&gt;Load Vue components directly for iterative development&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npm pack&lt;/code&gt; as part of predeployment testing&lt;/li&gt;
&lt;li&gt;Include Vue source files in NPM&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using vue-sfc-rollup
&lt;/h3&gt;

&lt;p&gt;This saves a lot of time, and it is always good to let someone else do the &lt;em&gt;undifferentiated&lt;/em&gt; heavy lifting. I could come up with something &lt;code&gt;better&lt;/code&gt; but it would use up effort that would be  better applied elsewhere. No matter how much &lt;code&gt;"better"&lt;/code&gt; I made it the build process would never be something that moved the dial on the business end of things.&lt;/p&gt;

&lt;p&gt;In short, you just install the &lt;code&gt;vue-sfc-rollup&lt;/code&gt; NPM and run the command &lt;code&gt;sfc-init&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vue-sfc-rollup
sfc-init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will lead you though choosing to export a single module or a library as well as whether to use Vue 2 or 3. I'm sticking with Vue 2 until Vuetify support for Vue 3 is fully baked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Loading Vue components from source
&lt;/h3&gt;

&lt;p&gt;In this instance I needed to include the &lt;code&gt;src/lib-components/*&lt;/code&gt; directly. &lt;/p&gt;

&lt;p&gt;This:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Multicorder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;multicorder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;changes to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Multicorder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../src/lib-components/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I need to deal with that scenario for a while I'll add something to the build step to make sure that link is always correct when the NPM is published.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;vue-sfc-rollup&lt;/code&gt; package provides a dev server, but it's not useful for creating UI's that depend on libraries like Vuetify. &lt;/p&gt;

&lt;h3&gt;
  
  
  Test NPM with locally
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;npm pack&lt;/code&gt; to create a &lt;code&gt;.tgz&lt;/code&gt; file that can be installed as an npm. The file name depends on the version number in the &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That can be installed with &lt;code&gt;npm install &amp;lt;path to *.tgz&amp;gt;&lt;/code&gt; syntax.&lt;/p&gt;

&lt;p&gt;In the Multicorder Vuetify UI that means running something liek this for the &lt;code&gt;vuetify_ui&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; ../multicorder-1.10.0.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Including Vue source files in NPM
&lt;/h3&gt;

&lt;p&gt;I export the Vue source files for the main component as well as the Vuetify UI. This provides context within the NPM as well as enabling direct access of those files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"dist/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.vue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"vuetify_ui/**/*.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"vuetify_ui/**/*.vue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"vuetify_ui/**/*.json"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
