StencilJS: Disable auto generation of readme files for some components - stenciljs

StencilJS auto generation is great: https://stenciljs.com/docs/docs-readme
Is there any way I can disable it for certain components?
Hopefully something simple like adding a line to the top of the tsx file?

If this feature existed I suspect that it would probably be based on a JSDoc comment, likely #ignore.
I just tested this by adding those comments and they seem to be ignored since the readme builds anyway.
I suggest opening an feature request issue in the ionic-team/stencil repository. An important detail would be if those components should also be hidden from the Dependencies section of other (non-ignored) components.
You could also try implementing it yourself, I think filtering the components here should work.
Update
There is an undocumented feature to achieve this by adding #internal to the JSDoc.
I just successfully tested it for components as well as only for specific properties in Stencil 1.12.5 but from looking at the git history it seems this has been available for a while (a couple of years at least).
Examples:
Ignore component:
/** #internal **/
#Component({...})
export class MyComponent {...}
Single property
#Component({...})
export class MyComponent {
#Prop() visibleProp = '';
/** #internal **/
#Prop() hiddenProp = '';
}

Related

How to properly override a default spartacus Component

For the most part overriding an existing Spartacus works fine.
The Minimum amount of effort is
B2cStorefrontModule.withConfig({
cmsComponents: {
DefaultComponent: {
component: CustomComponent
}
},
Mostly I do this because I need to apply some changes to the components html.
So I copy and paste it to my generated customComponent.
But most of the times this html contains directives and pipes that require adding additional Modules to my app.modules.
Sometimes this works fine, but in many other cases the html just wont render.
Example: SearchBoxComponent
when trying to use the html I get a browser Error:
Error: Template parse errors:
The pipe 'cxHighlight' could not be found ("
<a
*ngFor="let suggestion of result.suggestions"
[innerHTML]="[ERROR ->]suggestion | cxHighlight: searchInput.value"
[routerLink]="
{
"): ng:///AppModule/EmvSearchBoxComponent.html#49:21
In other cases I was able to fix this by including the corresponding module that references this pipe "cxHighlight". In this case "SearchBoxModule". But still no good.
How do make this pipe available in my project?
Or maybe there is an even better way around all this importing pain?
You are correct in the way you are overriding components in Spartacus. Like you noticed certain components contain pipes so you will have to manually import those in your components module. This is just the Angular way.
Most of our pipes are reused in multiple components so we try to make them have their own modules to make imports easier.
You are correct about cxHighlight, there is a bug. The pipe is declared in the SearchBoxModule but not exported so it's pretty much impossible to import. I will open an issue to have it fixed.

How to lazy load a plugin in Vue?

Vue plugins usually requires a global setup in app entrypoint by Vue.use(somePlugin). Doing so increases the bundle size for all pages, which is often bad and that it is better to defer the downloading of the module until when the module is actually being used, aka lazy loading or code spliting.
How do I lazy load a plugin if only one page in my Vue app needs it?
To answer the OP's question more directly: You can't lazy load a plugin.
According to the documentation, plugins by definition provide globally-accessible functionality and must be setup with Vue.use() before the Vue instance is created. Due to this, they'll always be bundled with the entire Vue instance (in a vendors chunk, for example).
What you want is to lazy load the functionality in a smaller scope, at a component level. Depending on the plugin, the plugin module should also support some sort of direct code importing at a component level, like this one does. Because it just uses import statements, they can be async loaded.
TL;DR: Anything using Vue.use() can't be lazy loaded. Async imports can.
One of the options is to call your plugin file in created/mounted hook and do the stuff you want.
Just import it on the specific page an example would be "Slide" from "vue-burger-menu"
<script>
import { Slide } from "vue-burger-menu"
export default {
components: {
Slide
}
}
</script>

Dynamic publicPath When Rendering Pages with Vue SSR

We're happy users of Vue and its server-side rendering module, Vue SSR. One of the requirements of my project is that we be able to dynamically adjust Webpack's publicPath at runtime, so that we can obtain assets from our different CDNs (we have two, one for test and one for prod).
We are able to accomplish this easily on the client-side using the __webpack_public_path__ free variable, and you can also override the publicPath within the SSR client manifest for asset URLs injected into the <head>.
Yet we continue to have issues with asset URLs that are housed directly within our templates and are rendered by SSR. For example, imagine if we had the following image within our tag:
<img src="~#/test.png" />
Our goal is that, on both the server and the client, we could adjust that URL to be prefixed how we please via publicPath. There doesn't seem to be a way to dynamically update the publicPath once the vue-ssr-server-manifest.json has been generated, the resulting URL ends up being something relative like /static/test.png or whatever we original cited in our Webpack config.
Per our project constraints, it's not possible to rebuild our SSR bundle, so we need to do this at runtime. We've tried adding placeholder values as our publicPath, e.g. __CUSTOM_WEBPACK_PUBLIC_PATH__, and replacing them in the server bundle at runtime, but that ends up being ineffective since publicPath is also embedded in other Webpack generated files.
Wondering if there is a cleaner way to achieve what we need directly via Vue SSR, or if this is something we just can't configure at runtime. Thanks for reading!
Late follow-up here, but we eventually solved this issue.
We found that setting __webpack_public_path__ globally in our Node.js process did result in the correct public path being applied to our assets in our server bundle.
Once that global is present both on the window (e.g. client-side), and globally in the node process (e.g. server-side), things started working as we wanted.
We faced similar type of problems in our webapp as well. BTW, we implemented a CDN plugin for vue.
export const CDNPlugin = {
install(Vue, { CDN, assetsManifest }) {
Vue.prototype.$cdn = {
...CDN,
asset(name) {
return `${CDN.baseUrl}${assetsManifest[name]}`;
},
resource(filepath) {
return `${CDN.baseUrl}/resources/${filepath}`;
}
};
}
};
Install this plugin both of your ssr and csr file.
Vue.use(CDNPlugin, {
CDN: { baseUrl: 'https://my.static.cdn.com' },
assetsManifest: yourAssetManifestObject,
});
And the usage of this CDN plugin inside vue template is as below
<img :src="$cdn.asset('relative/path/to/asset/style.css')">
If you think it is helping a bit, then I can share more regarding our implementation.
I spent an entire day trying to figure this out. In the end I used this:
https://github.com/agoldis/webpack-require-from
Worked like a charm, client side and server. Be aware you need to set a global.MY_BASE_URL in your node/server somewhere AND you need to inject a window.MY_BASE_URL somewhere in your HTML. Then just configure webpack.
plugins.push(new WebpackRequireFrom({variableName: 'MY_BASE_URL'}));
Similar problem occurred in my project, and finally I worked it out.
Ryan's answer really helps, but there is one thing I want to clear up. __webpack_public_path__ is a LOCAL variable in webpack bundled code, which means __webpack_public_path__ and global.__webpack_public_path__ is not the same. You need to do something like
__webpack_public_path__ = process.env.ASSET_PATH;
to specify public path (https://webpack.js.org/guides/public-path/#on-the-fly FYI).
Last, please make sure your process.env.ASSET_PATH is not undefined, maybe you have to set it manually to global in your server code.
global.process.env.ASSET_PATH = process.env.ASSET_PATH;

Custom Login page in Docusaurus

I have a task at work, It is to implement the login page inside the Docusaurus.
I am trying to customizing the index.js by adding some HelloWorld. Including login.js which has actual Docusaurus Index page
const Index = require('./login.js');
const React = require('react');
class Button extends React.Component {
render() {
return ("helloworld");}
}
module.exports = Button;
But Error thrown is:
Error: Cannot find module './login.js'
Is it possible to call the class from another js page in Docusaurus?
Docusaurus maintainer here! Yes, it should be possible as the current module system is CommonJS. You have to put that component in the same directory as index.js. Link me to a repository if possible and I can help you take a look.
On a side note, it doesn't make much sense to build a login form for Docusaurus as Docusaurus generates a static site that loses state across page navigations unless you persist them in cookies or localStorage. It'd be quite troublesome to do so. Maybe you could explain what you're trying to build here and I can recommend you better alternatives.
I found a way to work this out, even though there is no official documentation on this matter. I used the Docusaurus Swizzle to intervene in the Root component so that I can use Firebase Authentication (I think that you can use Auth0 or any custom logic in replacement).
I wrote a detailed blog on this so that I hope it can help others, you can see it here: https://medium.com/#thomasdevshare/docusaurus-authentication-with-firebase-c824da24bc51
There is also full example source code in the article, you can clone it.
First of all. What does "login.js" look like? It is an exported module with a well defined (default) namespace?
Secondly, you shouldn't add the file extension to an import. It's "require('./login')" not "require('./login.js')".

Vue JSX bind to class name

I'm building a simple TodoMVC app using Vue + JSX, but the documentation seems to be seriously lacking. Thus, I'm writing down the points I need to address as part of a CR to the appropriate projects. The only document I've read as of yet is the guide, which doesn't cover much JSX at all. I don't know much about how the framework works yet, but I sure prefer using the render method over the string templates for performance/network reasons.
question
What's the proper way to create a class name binding in Vue + JSX? In my TodoItem component, creating either a class or className attribute makes Babel throw a compile error complaining the API is deprecated (and suggesting I add several seemingly unrelated dependencies to the mix). Plus, including the class property in the data object seems to change nothing.
secondary question
The lack of documentation, plus the wording on the guide gives the impression JSX is not the "proper" way to write Vue components. Is that so? What's the idiomatic way to do it, given I don't want to ship the compiler along with my app?
links
code on codepan
I sure prefer using the render method over the string templates for performance/network reasons.
If you're writing *.vue files and bundling them with vue-loader (Webpack), the HTML template gets compiled into a JavaScript render function anyway, so there isn't really any kind of performance issues in that sense.
On the other hand, if you're writing your Vue components with string templates like this:
new Vue({
template: '<div>Hello</div>'
})
then you'll need the Vue template compiler at runtime to convert the string into a render function.
Typically people would opt for writing render functions manually if they need to do something specific that would be difficult/impossible to do with the HTML template alone.
You've probably already read the docs, but just in case, the relevant sections are:
Render Functions & JSX
The Data Object In-Depth
babel-plugin-transform-vue-jsx Usage
What's the proper way to create a class name binding in Vue + JSX?
You would just bind to the class attribute like you would any other attribute:
<div class={this.klass}>
data() {
return {
klass: 'foo'
}
}
The lack of documentation, plus the wording on the guide gives the impression JSX is not the "proper" way to write Vue components. Is that so? What's the idiomatic way to do it, given I don't want to ship the compiler along with my app?
JSX is definitely supported, but it is not the recommended approach. The recommended approach is to write *.vue files and load them with vue-loader (if using Webpack).
Vue comes in two versions, one with and one without the template compiler. The one with the compiler included is only for development and should not be used for production builds (unless you require string template to render function compilation at runtime, which is unlikely). See Explanation of Build Files for more info.
Typically you write HTML string templates, and they get compiled to render functions (by vue-loader) at build time.