So you're using Vue.js and Webpack. Not for building a full web-application, but for building a reusable web component — i.e. a user-interface element that your consumers (=other developers) can use in their projects.
This project is a working webpack+npm configuration,
that supports three types of consumers for your Vue component:
• developers who use it as a standalone web-component;
• developers who prefer to only use a slim component build;
• developers who use it directly in their own Vue app.
-
Consumer type 1:
These developers don't want to deal with Vue or any Webpack setup. They only want to add one extra<script src="__.js">
-tag in the html-header, and use your component as a custom html-tag, like:<my-component attr1="...">...</my-component>
.- For them, we'll need to bundle the Vue framework, plus code that wraps the Vue-component into a web component (which makes it usable as a custom html-tag), into a single JS-file.
- For this we must build our Vue-component as a standalone web-component.
-
Consumer type 2:
These developers want to add multiple such web-components to their page. And they realize it would make their site slower, if the same Vue framework code would be included by each standalone component.- For these consumers, we need to build our Vue-component as a slim component. This is a build were the shared Vue code & web-component'ifying code is split off.
- Developers can then load this code (that supports all such 'slim'
components on the page) once, by adding some extra
<script>
-tags.
They must also add a few lines of code to 'activate' the component with Vue, but they can avoid setting up Webpack.
-
Consumer type 3:
These developers just want to import your Vue-component into their own, larger Vue component, or into their Vue app.- These developers will have their own Webpack setup.
So they can include either the .vue file directly, or (more efficiently) include the 'slim component' JS-code above. - This is the development setup.
- These developers will have their own Webpack setup.
There are small differences in how to programmatically interface
with a component, based on these three output types.
Therefore, if any of these differences pertain to your component,
you should make your consumers aware of them.
(This project fully describes them all).
This project includes:
- a complete Webpack setup to handle the three output types (standalone build, slim build, and development setup);
- three use-cases that demonstrate using the three types; with comments that point out the differences;
- an integrated testing setup with 'mocha-webpack' and 'vue-test-utils';
- an integrated linting setup with 'ESLint';
- npm-script commands to launch all of the above.
-
package.json
: thescripts
section shows the differentnpm
commands
(after you rannpm install
first) :npm start
bundles the code for the browser, starts a Webpack dev-server, and opens the demo pageindex-dev.html
(incl.index-dev.js
).npm run build
launches two build processes:build:slim
andbuild:standalone
.- These compile both the slim and standalone JS-code into the
dist
folder, namedmy-component.min.js
andmy-component.standalone.min.js
respectively.
- These compile both the slim and standalone JS-code into the
npm test
runs the test code.npm run testw
runs the test code in watch-mode (auto-retests on file changes).npm run testwi
does the same but does not clear the console.npm run dev
runsstart
andtestwi
in parallel, so you can use a single console-window during development, to see webpack and test errors.npm run lint
runs style checks on the code.- These checks are automatically run during the dev/test/builds as well.
- During dev/test they produce only non-breaking warnings instead of errors.
-
webpack.config.js
: the Webpack configuration file.- Some people scatter Webpack config over multiple files.
Others group it all together, and structure it by topic.
We chose for the clear, single-file approach, where we activate conditional config options like:
Object.assign( {setting1}, DEV ? {setting2} || {} )
. - This config was inspired by sources all over the web. Where it's maybe less obvious, we added comments.
- (On top of the file you see all
npm install
ed packages. This is useful if you'd want to reinstall all packages to their latest major version).
- Some people scatter Webpack config over multiple files.
Others group it all together, and structure it by topic.
-
.eslintrc.js
: ESLint config options.- This includes both recommended EcmaScript and Vue.js code and code-style checks.
- When using
npm lint
, these are the exact options. But for other build processes these may be overridden by options in webpack.
-
src/MyComponent.vue
: a small demo Vue-component. It is simply:- a button to increase a counter;
- the counter's value;
- the initial count-value, which can be set by an HTML-attribute ('prop') on the component;
- a value that is given by a getValue() function, located in an Object
that can be given as a prop on the component;
- this is used for showing how to set an Object or class (i.e. not a String) attribute on a standalone web-component;
- an event-emitter that fires after the button increased the value;
- this is used for showing how to add an event-listener to a standalone web-component.
-
src/MyComponent.test.js
: a small demo of testing some aspects of the Vue-component. This shows that tests are well integrated in the webpack setup. -
src/test-setup.js
: this file is included before any tests are run. -
src/index-dev.html
+src/index-dev.js
: the live demo of the Vue-component, served in a webpage, used during development.- These need to be two separate files, so that 'webpack-dev-server' can use 'index-dev.js' as a JS entry-point to find all the other JS code that it should bundle.
- This demonstrates four aspects of using the component:
- how to give a non-string prop (=attribute);
- how to attach an event listener;
- how to change a prop after component creation;
- how to dynamically add an extra instance of the component, that was not present in the webpage originally.
-
index-prod-slim.html
: demo of using the 'slim' build.- It treats the same four aspects as in 'index-dev', with comments on differences in use.
- It shows how to load the external dependencies in <script>-tags:
- 'document-register-element'
(which allows Vue components to be wrapped into a web-component,
so that we can insert MyComponent as a
<my-component>
tag), - 'vue', and
- 'vue-custom-element':
<script src="https://unpkg.com/document-register-element"></script> <script src="https://unpkg.com/vue"></script> <script src="https://unpkg.com/vue-custom-element"></script>
- 'document-register-element'
(which allows Vue components to be wrapped into a web-component,
so that we can insert MyComponent as a
- And it shows that the
<my-component>
tag must be located within another tag, e.g.:on which the Vue framework must be activated like this:<div id="app"> <my-component attr="..."></my-component> </div>
<script> Vue.customElement('my-component', MyComponent.default); new Vue({ el: '#app' }); </script>
-
index-prod-standalone.html
: demo of using the 'standalone' web-component build.- It treats the same four aspects as in 'index-dev' / 'index-prod-slim', with comments on differences in use.
- Here, no other <script>-tag needs to be added, and
the<my-component>
tag can be used anywhere on the web page.
-
index-prods.html
: this includes bothindex-prod-slim.html
andindex-prod-standalone.html
in two <iframe>s on the same web page.
This enables us to verify at one glance (automatically afternpm build
) that both bundle types still work correctly.
Read more in index-*.*
's comments, on the small differences in use
for the three build versions / consumer types.