Storybook doesn't work with renamed exports - javascript

I am writing a component library in/for react and using Rollup to bundle it. As part of the build process I am using Terser to make sure the bundle is as small as possible. As part of the minification process, Terser renames the variables and then renames then back at export. Like so:
export{_ as BtnResponsive,l as Button};
This works fine when importing my library into other ES modules. Like so:
import { BtnResponsive } from '#namespace/component-lib';
But when I create a Storybook story Button.stories.tsx and import my component like so:
import { ComponentStory, ComponentMeta } from '#storybook/react';
import { BtnResponsive } from '#namespace/component-lib';
export default {
title: 'Components/BtnResponsive',
component: BtnResponsive,
} as ComponentMeta<typeof BtnResponsive>;
const Template: ComponentStory<typeof BtnResponsive> = (args) => <BtnResponsive {...args} />;
export const Primary = Template.bind({});
Primary.args = { children: 'Primary', theme: 'primary' };
Storybook then renders the component in my story like
<_ theme="primary">
Primary
</_>
Storybook somehow doesn't respect the renamed export. Does anyone know how to either make storybook respect the component name? or know how I can adjust Terser so Storybook understands the name correctly?
Thanks in advance!

Terser apparently has options that you can use to prevent it from mangling function names. In my rollup.config.js I had to add the following:
terser({
keep_fnames: true,
})

Related

Use index file to export .tsx modules

It's a common thing to create a index.js file in an React application with the only purpose to export several modules, in order to avoid having too many import statements on other components. This can be done by:
index.js
export { Credits } from './Credits.js';
export { SocialMedia } from './SocialMedia.js';
any module that might use those exports:
import * as var_name from index.js
And this is very nice. It wraps exports into a single file. However, when I changed my project to React with typescript, I found that .tsx files cannot be exported like that. The image below is the error I got after changing the project to typescript and the extensions became .tsx
Is there a way of 'bundle' export React .tsx files with the structure shown above? If not, what is the simplest way of centralizing .tsx files export?
My webpack.config.js:
module.exports = {
module: {
rules: [{
test: /\.scss$/,
use: ["sass-loader"]
}]
}
};
You can definitely use the same style of having an index file to group up exports for a whole folder. The simplest way around your problem would be to omit the file extension (assuming you only have one "index" file in the folder).
For example, let's say you have a component in 'common/Example.tsx':
import React from 'react'
export const Example = () => (<div>I'm an example component</div>)
You can then export it in an index file 'common/index.tsx':
export { Example } from './Example'
And import it from somewhere else, e.g. 'App.tsx':
import { Example } from './common'

How to to change the default file from index to a custom in React Components?

Structure of the project generally looks like this:
components
- my-component
- - my-component.ts
- - index.ts
Where index.(ts/js) always consists of
import MyComponent from './my-component';
export default MyComponent;
I want to remove index.(js/ts) and still import/require my components using the path
import MyComponent from './components/my-component' // not having the index file!
// Please, do not suggest importing them like this
import MyComponent from './components/my-component/my-component'
I use Webpack 5. I know there was a module for Webpack 4, but it does not work with 5.
I want NodeJS/Webpack to look for a custom filename rather than index.
Some other solutions:
You could move components/my-component/my-component.ts to components/my-component.ts. I assume you have a reason not to do this (presumably, other files in that component directory).
You could use resolve.alias and list all mappings you want:
module.exports = {
//...
resolve: {
alias: {
"./components/my-component": path.resolve(__dirname, 'components/my-component/my-component.js'),
//...
},
},
};
You could set resolve.mainFiles to list all of your .js filenames. This seems pretty ugly though, as it's a global setting.
Are you sure that Webpack 5 doesn't support DirectoryNamedWebpackPlugin? It's explicitly mentioned in the documentation.

module.exports does not contain a default export

I am trying to export my theme in my react app using `module.exports =
module.exports = {
defaultFontColor: "#282828",
name: "Planswell",
primary: primary,
deemphasizedPrimary: "#e7f6ee",
secondary: "#E4A432",
danger: "#DF5F2B"...}`
in my file whatever.js, and i try to import it in another file using import whatever from "themes/whatever.js";
All was working well, but i updated Babel, and am now getting the error Attempted import error: 'themes/whatever.js' does not contain a default export (imported as 'whatever').
What changed with Babel that caused this error? And how do I fix it?
If the only export in your whatever.js is
module.exports = {mod1, mod2, ...}
Then, assuming whatever is actually a module in your file, you should have never been able to import it using
import whatever from "themes/whatever.js";
The only way that would be possible is if in your whatever.js you did:
export default whatever;
Otherwise, you will have to destructure the import like so:
import {whatever, mod1, mod2, ...} from "themes/whatever.js";
Again, all this assumes that whatever is actually a module inside your whatever.js file e.g const whatever = () => {.... You don't make that part clear.
The error you're getting should help you guide your way. When using module.exports = {...} syntax, the default export is the object.
You should try importing specific exported properties of the module such as import { someModule } from 'themes/whatever.js'. Optionally you can use
import * as whatever from 'themes/whatever.js'
// Use it
whatever.myFunction()
Babel is pretty complex tool so I would check from which version you upgraded to and then looked at the change log to see what has changed. Babel has plethora of presets and plugins so it could be any combination, sorry no simple answer here.
To me it seems like perhaps you're using some different type of module.
Maybe you are using #babel/preset-env with combination of browserslist settings and you transpile to ES6 modules?
in your whatever.js you have exporting the as an object that contain your component so you have to export it like this
import {whatever} from "themes/whatever.js";
for your example to work you have to export your component without brackets
export {whatever}

Importing single file components VueJS

everyone.
I have a trivial doubt on making vue components.
I don't want to use browserify or webpack , cause I am working in django and it has most of it's templates in static files , although I read this , which does describe how to take in account both ( but that's for some other day ).
Problem :
I am making a single file component which I have to import and use, using my router but I can't, as the import just doesn't happen.
My Hello.vue
<template>
Some HTML code here.
</template>
<script>
module.exports = {
data() {
return {
coin : []
}
},
beforeRouteEnter (to, from, next) {
axios.get('my-django-rest-api-url')
.then(response => {
next(vm => {
vm.data = response.data
})
})
}
}
</script>
I have it in the index.html file itself , no other .js file,
<script>
import Hello from '#/components/Hello.vue'
Vue.use(VueRouter);
const dashboard = {template:'<p>This is the base template</p>'};
const profile = {
template: '#profile_template',
data () {
return {
profile_details: []
}
},
beforeRouteEnter (to, from, next) {
axios.get('my-api-url')
.then(response => {
next(vm => {
vm.profile_details = response.data
})
})
}
}
const router = new VueRouter({
routes: [
{ path: '/', component: dashboard },
{ path: '/profile', component: profile },
{ path: '/hello', component: Hello }
]
});
new Vue({
router : router,
}).$mount('#app');
</script>
What all I've tried :
1.<script src="../components/Hello.js" type="module"></script> and removing the import statement as suggested here
Replacing my Hello.js's code with this : export const Hello = { ...
Making a Hello.js file and importing it like this import Hello from '../components/Hello.js';
Error :
**Mozilla ( Quantum 57.0.4 64 bit ) ** : SyntaxError: import declarations may only appear at top level of a module
**Chrome ( 63.0.3239.108 (Official Build) (64-bit) ) ** :Uncaught SyntaxError: Unexpected identifier
P.S. : I have tried these in various combinations
Not a Vue.js guru, but here are a few perspectives that might help you.
Module loading is still not supported on modern browsers by default, and you'd need to set special flags in order to enable it (which the users of your app probably won't do).
If you insist on using import and export, you'd need Webpack. And most certainly Babel (or any other ES6 transpiler, e.g. Buble) as well.
If you prefer module.exports, then you'd need Browserify. It enables support for CommonJS in browser environments.
If neither is doable, then your best bet is defining Vue components in global scope. You can split them across separate files, and import each with a <script> individually. Definitely not the cleanest approach.
Single file components typically go inside of .vue files, but either way they require vue-loader which can be added and configured (again) with a bundler.
Last option is to just use an existing setup in place, if there is any (is there?). If you already have RequireJS, UMD, or something similar in place, adjust your components to fit that. Otherwise, use <script>s.
You are trying to do something which is not possible. Vue Single file components are not supported as raw component file by web browsers. The single file component is supposed to be compiled.
Please see this for more:
https://v2.vuejs.org/v2/guide/single-file-components.html
In Webpack, each file can be transformed by a “loader” before being included in the bundle, and Vue offers the vue-loader plugin to translate single-file (.vue) components.
A vue single file component is first "translated" (compiled) to pure javascript code which is use-able by browsers.

How to fix eslint errors in meteor with react tutorial

I've followed meteor tutorial, and when I finished I've decided to install eslint.
Now I see
Prefer default export import/prefer-default-export
for this line: export const Tasks = new Mongo.Collection('tasks'); in imports/api/tasks.js file. It contains also some Meteor methods. Here it is full source code: tasks.js.
I was trying to fix this eg. with
const Tasks = new Mongo.Collection('tasks');
export { Tasks as default };
But then browser stopped rendering the view.
Here is the server/main.js content, which imports tasks.js:
import '../imports/api/tasks.js';
How can I fix lint error without breaking applications functionality?
You could add an .eslintrc file to your project root and adapt the rule:
{"rules": {"import/prefer-default-export": ["off"]}}
UPDATE:
If you want to keep the rule, then you need to export Tasks as default like so:
const Tasks = new Mongo.Collection('tasks');
export default Tasks;
Now you have to change all the imports in the rest of your codebase from a named import to a default import. The named import looks like this
import { Tasks } from '/imports/api/tasks';
see e.g. here, whereas the new default import has to look like this
import Tasks from '/imports/api/tasks';
This should do it. Let me know if it works for you.

Categories