-
Notifications
You must be signed in to change notification settings - Fork 140
Fragment-common, Vue 3 & RequireJS #343
Comments
I would discourage you from loading "common" scripts. This comes from
experience.
The problems you are trying to solve like repeating the code, loading
commonly used files across fragments/URLs and reducing duplication of code
in the code-base requires a different approach.
In our solution we have fallen into the common script trap and now find
ourselves too coupled and unable to release smaller changes without always
releasing the common fragment. I think that using bundler's tree-shaking
capabilities can be helpful and potentially a better approach. Check this
out:
https://webpack.js.org/guides/tree-shaking/
https://parceljs.org/features/code-splitting/#tree-shaking
This does mean you will have to do a bit of extra work to make sure any
legacy code is written to be tree-shaken (in proper module syntax). But,
this will pay off in the long run. Hope this helps!
…On Mon, Oct 18, 2021 at 9:28 AM Oskar Nilsen Roos ***@***.***> wrote:
Hi! I've been trying to create a "fragment-common" for resources that are
to be shared between our micro frontends, and I haven't been able to find
an example of someone bundling Vue as a shared resource.
The only way I got it working was through a script tag, pointing to a
bundle.js with Vue. However, what we actually want is a regular fragment
tag so we can point our shared JS resources through a Link header instead,
but I haven't been able to get this working.
My current solution looks something like this:
*common.js*
exports.Vue = require('vue/dist/vue.esm-bundler')
*webpack.config.js*
var webpack = require('webpack')
module.exports = {
entry: './common.js',
output: {
path: __dirname + '/public',
publicPath: 'http://localhost:6006/public/',
filename: 'bundle.js',
libraryTarget: 'umd',
},}
*base-template.html*
<head>
<script src="http://localhost:6006/fragment-common/public/bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.min.js" crossorigin=""></script></head><body>
<p id="app">{{user}}</p>
<script>
const RootComponent = {
setup() {
return {user: 'Test'};
}
};
const app = Vue.createApp(RootComponent);
app.mount('#app');
</script></body>
And this also comes with a caveat, I noticed that if RequireJS
(automatically imported by tailor) comes before the bundle.js script, Vue
won't load. I don't know why this is. As far as I know there's no nice way
to make sure RequireJS loads after, but I solved it by passing an empty
string to the amdLoader option in the Tailor config like so:
const tailor = new Tailor({
fetchTemplate: fetchTemplateFs(
path.join(__dirname, 'templates'),
baseTemplateHeaderFn
),
fetchContext: (req) => {
...
},
filterRequestHeaders: filterHeadersFn,
amdLoaderUrl: ""
)}
Which results in the following when Tailor tries to set it:
<script src="" crossorigin=""></script>
Where it is later imported manually by setting it in the template instead.
I have tried different ways of solving this, with different webpack builds
and also this solution
<#196 (comment)>,
but to no avail.
*TLDR:* How do I share Vue in a common fragment, passing it with a Link
header to Tailor on fragment request?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#343>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AANQN267OKLPWC5AAA7LLATUHQOHZANCNFSM5GGVAQXQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
Thank you for your input, that does make sense. We have thought some about what it's going to look like when we, for example, eventually transition from all apps running Vue 3, to all except one which is running Vue 4. In this case we'd have to bundle two different versions of Vue into our common fragment until all have transitioned properly. Is this similar to how you've had to solve it too? I'm not too familiar with tree shaking, is it possible for it to solve my Vue issue, as in at runtime? I read the article but as far as I can understand it only applies to reducing dead code in the same project, not across several different apps running on the same page, potentially with different build configs. Do correct me if I'm wrong! |
I don't think tree-shaking will solve the problem of having two separate
versions of Vue in fragments within one URL. You will have to live with the
initial page load time slowness. Potentially you can load the resources
async, and use caching for the Vue lib code.
…On Tue, Oct 19, 2021 at 10:55 AM Oskar Nilsen Roos ***@***.***> wrote:
Thank you for your input, that does make sense. We have thought some about
what it's going to look like when we, for example, eventually transition
from all apps running Vue 3, to all except one which is running Vue 4. In
this case we'd have to bundle two different versions of Vue into our common
fragment until all have transitioned properly. Is this similar to how
you've had to solve it too?
I'm not too familiar with tree shaking, is it possible for it to solve my
Vue issue, as in at runtime? I read the article but as far as I can
understand it only applies to reducing dead code in the same project, not
across several different apps running on the same page, potentially with
different build configs. Do correct me if I'm wrong!
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#343 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AANQN27RHI5CM5BU7GVCPRDUHWBFPANCNFSM5GGVAQXQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
Okay, then our current solution doesn't seem too bad to share Vue between a few fragments 😄 But I will keep in mind your tip of not getting stuck in the script trap. Tree-shaking still seems like it would be a great addition to reduce our load times though! If people don't mind I'd like to keep the issue open for anyone that might have solved this with the RequireJS define script, or ran into the weird Vue + RequireJS load order thing. |
@Oskar-Nilsen-Roos not sure it helps you now but what we do is as follows:
on each one of the fragments we define these packages as externals
we use tree shaking and each fragment is about 90kb. our common fragments do not only bring libraries but we also initialize redux store and populate cross-application data in the store so all fragments can access if they need. (we still maintain a clear separation of concerns between fragments, common is the exception) we use redux dynamic modules to be able to append reducers to store post initialization. hops thats help somehow. |
Hi! I've been trying to create a "fragment-common" for resources that are to be shared between our micro frontends, and I haven't been able to find an example of someone bundling Vue as a shared resource.
The only way I got it working was through a script tag, pointing to a bundle.js with Vue. However, what we actually want is a regular fragment tag so we can point our shared JS resources through a Link header instead, but I haven't been able to get this working.
My current solution looks something like this:
common.js
webpack.config.js
base-template.html
And this also comes with a caveat, I noticed that if RequireJS (automatically imported by tailor) comes before the
bundle.js
script, Vue won't load. I don't know why this is. As far as I know there's no nice way to make sure RequireJS loads after, but I solved it by passing an empty string to theamdLoaderURL
option in the Tailor config like so:Which results in the following when Tailor tries to set it:
Where it is later imported manually by setting it in the template instead.
I have tried different ways of solving this, with different webpack builds and also this solution, but to no avail.
TLDR: How do I share Vue in a common fragment, passing it with a Link header to Tailor on fragment request?
The text was updated successfully, but these errors were encountered: