Base url with multi page apps using vite - rollupjs

For my multi page app i cannot have html assets imports pointing to the root as i need to upload my project inside a sub-folder.
Using -
module.exports = defineConfig({
base: "./",
});
resolves this issue for root pages but cause a wrong import for nested pages.
Example
- assets
- index.html
- nested
- nested.html
Imports for index.html will point to ./assets which is correct.
Imports for nested.html will also point to ./assets which is incorrect. It needs to point to ../assets instead.

You can set an alias to point to the assets folder :
alias: {
"#": resolve(__dirname, './assets'),
},
Based on your tree sample, with this following example of multipage vite.config.js, you can import assets
from components with: import logo from '#/logo.png' (assuming there is a logo.png file in folder assets)
import vue from "#vitejs/plugin-vue";
import { join, parse, resolve } from "path";
export default {
base: '',
root: './',
plugins: [vue()],
alias: {
"#": resolve(__dirname, './assets'), // will resolve to `/assets/`
},
build: {
rollupOptions: {
input: entryPoints(
"index.html",
"nested/nested.html",
"foo/index.html",
"foo/bar/index.html",
),
},
},
};
function entryPoints(...paths) {
const entries = paths.map(parse).map(entry => {
const { dir, base, name, ext } = entry;
const key = join(dir, name);
const path = resolve(__dirname, dir, base);
return [key, path];
});
const config = Object.fromEntries(entries);
return config;
}
Example code of the nested FooBar component :
<template>
<img alt="Vue logo" :src="logo" />
<Nav/>
<h1>Foo Bar</h1>
</template>
<script setup>
import Nav from "~/components/Nav.vue";
import logo from '#/logo.png'
import "#/style/style.scss"
</script>

Related

Vite multi-page app not working for the extra pages

I have a file structure like so app(main) and dashboard(secondary) being the different pages
but when trying to open the secondary app at /
vite.config.js
import * as path from "path";
import { defineConfig } from "vite";
import react from "vite-preset-react";
import svgr from 'vite-plugin-svgr'
import rollupReplace from "#rollup/plugin-replace";
const outDir = path.resolve(__dirname, 'build')
export default defineConfig({
plugins: [
rollupReplace({
preventAssignment: true,
values: {
__DEV__: JSON.stringify(true),
"process.env.NODE_ENV": JSON.stringify("development")
}
}),
react(),
svgr()
],
root: 'app',
build: {
root: outDir,
rollupOptions: {
input: {
app: path.resolve(__dirname, "app/index.html"),
dashboard: path.resolve(__dirname, "dashboard/index.html"),
}
}
},
});
and the server.js file is just an empty file not used

Webpacker, babel, uglifyjs-webpack-plugin - not transforming arrow functions, but only in Vue files

Running webpacker 3.5.5 (both the gem and package). This is mostly working, but in IE11 the app is broken because arrow functions do not appear to be transformed. However, inspecting the minified code it seems like the only place arrow functions aren't transformed are inside my vue components.
I think this is because my babel class properties plugin is not applying to my Vue loader somehow, but I haven't been able to come up with a solution.
Here's my .babelrc
{
"presets": [
[
"env",
{
"modules": false,
"targets": {
"browsers": [
"> 1%",
"IE 11"
],
"uglify": true
},
"useBuiltIns": true
}
]
],
"plugins": [
"syntax-dynamic-import",
"transform-object-rest-spread",
[
"transform-class-properties",
{
"spec": true
}
]
],
"env": {
"test": {
"presets": ["es2015"]
}
}
}
And here's the entirety of my environment.js file that modifies the webpack environment that webpacker ships with (vue loader is at the bottom).
const { environment } = require('#rails/webpacker');
environment.loaders.append('expose', {
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
}]
});
const webpack = require('webpack');
// append some global plugins
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
axios: 'axios',
moment: 'moment-timezone',
_: 'lodash'
}));
// Necesary configuration for vue-loader v15
const VueLoaderPlugin = require('vue-loader/lib/plugin');
environment.plugins.append(
'VueLoaderPlugin',
new VueLoaderPlugin()
);
environment.loaders.append('vue', {
test: /\.vue$/,
loader: 'vue-loader'
});
module.exports = environment;
Edit for more info: Here is the entry point to my pack called 'wrestling'
import 'babel-polyfill';
import 'wrestling';
Then in wrestling.js...
import './styles/wrestling'
import Rails from 'rails-ujs'
Rails.start();
import wrestlingSetup from './wrestlingSetup'
wrestlingSetup();
WrestlingSetup contains the actual references to the vue files. I've cut down the file to show what a single vue import looks like within the file. All the rest are essentially the same.
import Vue from 'vue/dist/vue.esm'
// Redacted a bunch of imports, but they all look like this oen
import WrestlerCreate from './vue/wrestler_create.vue'
export default function() {
document.addEventListener('DOMContentLoaded', () => {
axiosSetup();
const app = new Vue({
el: '#app',
components: {
// Other vue components here that I've removed for simplicity
WrestlerCreate,
}
})
});
}
Here's an actual example of the Vue component
<template>
<div role="form">
<!-- other form elements -->
</div>
</template>
<script>
export default {
name: 'wrestler-create',
props: [
],
// This does not get transformed by babel
data() {
return {
loading: false,
error: false,
errorMessage: "Error, please try again later or contact support.",
first_name: '',
last_name: '',
weight_class: '',
academic_class: ''
}
},
methods: {
// removed for simplicity
}
}
</script>
For clarify sake:
Please use function() for data. I find function() gives me less trouble than arrow functions.
export default {
data: function() {
return {
message: "Hello something!",
secondMessage: "Hello world!"
};
}
}
If you really wish to use arrow function, you can write:
export default {
data: () => {
return {
message: "Hello something!",
secondMessage: "Hello world!"
};
}
}

How do rollup externals and globals work with esm targets

I have a question for all you Rollup gurus. I’m struggling with externals and globals. If I have a rollup.config.js like this:
const external = ['hyperhtml'];
const globals = {
'hyperhtml': 'hyperHTML'
};
export default [
{
external,
input: 'src/foo-bar.mjs',
plugins: [
],
output: {
file: 'dist/foo-bar.mjs',
format: 'es',
globals,
paths: {
hyperhtml: '../node_modules/hyperhtml/min.js'
},
}
},
];
And the entry (foo-bar.mjs) looks like this:
import { hyper } from '../node_modules/hyperhtml/min.js';
class FooBar extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.render();
}
disconnectedCallback() {}
render() {
hyper(this.shadowRoot)`
<div>something</div>
`;
}
}
customElements.get('foo-bar.mjs') || customElements.define('foo-bar.mjs', FooBar);
export { FooBar };
I would expect Rollup to replace the import {hyper} from ‘hyperhtml’ statement in the generated bundle with something like const {hyper} = hyperHTML but it doesn’t. Instead the bundle file looks like is the same as the source file. Can someone explain why?
If I remember correctly globals only works on iife modules and by extension umd ones, try with rollup-plugin-virtual (https://github.com/rollup/rollup-plugin-virtual)
export default [
{
input: 'src/foo-bar.mjs',
plugins: [
virtual ({
'node_modules/hyperhtml/min.js': `
export const hyper = someGlobalNamespace.hyperhtml.hyper;
`
})
],
output: {
file: 'dist/foo-bar.mjs',
format: 'es'
}
},
];
Not sure if it will work though...

how to import html files with webpack 2?

I can't figure out how to import html files with webpack 2! I am using angular 1.6.0 and typescript.
I would like to import a template and use it as a router state template:
import * as angular from 'angular';
import * as uiRouter from 'angular-ui-router';
import theView from './theView.html';
import appComp from './app.component';
export default angular
.module('app.main', [uiRouter])
.component('myAppComp', appComp)
.config(($stateProvider, $urlRouterProvider, $locationProvider) => {
'ngInject';
$locationProvider.hashPrefix('');
$stateProvider
.state('main', {
url: '/main',
template: '<p>main state template</p>'
})
.state('main.cardList', {
url: '/cardList',
template: theView
});
}
It gives:
error:
ERROR in ./src/app/module.ts
(3,22): error TS2307: Cannot find module './theView.html'.
What (wierd) I don't understand is if I import the template same as above and use it in a component template, it does gives same error "cannot find module './theView.html'" but it works!
This works (with ts compilation error):
import template from './theView.html';
.component(appComp, {
template
})
webpack.config:
module.exports = {
entry: './src/app/module.ts',
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.html$/,
use: [{ loader: 'html-loader' }]
}
]
},
output: {
filename: 'bundle.js',
path: __dirname + "/dist"
}
};
What is going on here..?
For the people who can come across this problem in the future; it is solved as follows:
declare const require: any;
$stateProvider
.state('main.cardList', {
url: '/cardList',
template: require('./theView.html').default
});
Credits to #yadejo for the answer above!

How to use css with webpack in a rails app?

Following the github docs, I tried the following to include scss assets in my app:
app/javascript/styles/app.scss:
#import 'https://fonts.googleapis.com/css?family=Roboto:300,400,500';
body {
margin: 0;
}
app/javascript/packs/application.js:
/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
// Support component names relative to this directory:
var componentRequireContext = require.context("components", true)
var ReactRailsUJS = require("react_ujs")
ReactRailsUJS.useContext(componentRequireContext)
import React from 'react';
import '../styles/app.scss'
My webpack.config.js is the default webpack installs on rails. It is a combination of these 2 directories:
https://github.com/rails/webpacker/tree/master/lib/install/config/loaders/core
https://github.com/rails/webpacker/tree/master/lib/install/config/webpack
I can find the CSS config in config/loaders/sass.js:
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const { env } = require('../configuration.js')
module.exports = {
test: /\.(scss|sass|css)$/i,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{ loader: 'css-loader', options: { minimize: env.NODE_ENV === 'production' } },
{ loader: 'postcss-loader', options: { sourceMap: true } },
'resolve-url-loader',
{ loader: 'sass-loader', options: { sourceMap: true } }
]
})
}
On doing this, I do not get any error but the stylesheet isn't imported. Serving the same file from the asset pipeline works fine.

Resources