How do I use `unpkg` with ViteJS? - vite

I'm migrating my Vue plugin from Vue CLI to Vitejs.
With vue-cli-service build I generate three files: index.common.js, index.umd.js and index.umd.min.js
In package.json I refer to these files with:
"main": "dist/index.common.js",
"unpkg": "dist/index.umd.min.js",
But now migrating to ViteJS npm run build creates js files with random strings index.25e1eb44.js.
How do I use unpkg with ViteJS in package.json?

By reading other code, I found a good solution:
import { defineConfig } from 'vite';
import vue from '#vitejs/plugin-vue';
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js';
const path = require('path');
// https://vitejs.dev/config/
export default defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'src/index.js'),
name: 'VueResponsiveVideoBackgroundPlayer',
fileName: 'vue-responsive-video-background-player',
},
rollupOptions: {
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// Add external deps here
globals: {
vue: 'Vue',
},
},
},
},
plugins: [
vue(),
cssInjectedByJsPlugin(),
],
});
For more, read here: https://vitejs.dev/config/build-options.html#build-commonjsoptions

Related

Include locales and stores on compiled mfe with vite plugin federation

I'm doing a microfrontend project using vite plugin federation. The mfe childs uses i18n and pinia.
After compiling and importing the mfe childs into de host, it doesn't work because it can't resolve de dependencies (i18n and pinia).
Error with i18n:
Uncaught TypeError: _ctx.$t is not a function
Error with pinia:
Uncaught Error: [🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia?
const pinia = createPinia()
app.use(pinia)
To resolve it, it's not enough installing these dependencies into the host, i also need to config i18n with the same json structure and pinia with the same stores structures.
Due to this, i'll have some duplicated files in different repositories so i think it's not the best way to handle this.
Do you have any workaround idea?
(mfe-child) vite.config.ts
export default defineConfig({
plugins: [
vue(),
federation({
name: "mfe-boilerplate",
filename: "remoteEntry.js",
exposes: {
"./ExampleView": "./src/modules/example-module/views/ExampleView.vue",
},
shared: ["vue", "vue-i18n", "pinia"],
}),
vueI18n({
include: path.resolve(__dirname, "./src/locales/**"),
compositionOnly: true,
}),
],
build: {
minify: false,
}
});
(mfe-host) vite.config.ts
export default defineConfig({
plugins: [
vue(),
federation({
name: "host-app",
remotes: {
mfe_boilerplate: "http://localhost:4174/assets/remoteEntry.js",
},
shared: ["vue", "vue-i18n", "pinia"],
}),
],
});
Additional config to make i18n work:
(mfe-host) main.ts
const i18n = createI18n({
locale: "en",
messages: { // this is the same JSON structure and content from mfe-child
en: {
"mfe-child-page-title": "Title from host"
},
},
});
app.use(i18n);

Why Vite build throw the Error [commonjs--resolver] Failed to resolve entry for package

I have some package on the node modules that have a package.json
{
"sideEffects": false,
"module": "./index.js",
"main": "../node/{moduleName}/index.js",
"types": "./index.d.ts"
}
When vite trying to build it throw the error
[commonjs--resolver] Failed to resolve entry for package "/drone/src/node_modules/{module}/core/node_modules/#mui/material/LinearProgress". The package may have incorrect main/module/exports specified in its package.json: ENOENT: no such file or directory, lstat '/drone/src/node_modules/{module}/core/node_modules/#mui/material/LinearProgress/index.js'
error during build:
My vite config is
import { defineConfig } from 'vite';
import RubyPlugin from 'vite-plugin-ruby';
export default defineConfig({
build: {
assetsInlineLimit: 2048,
rollupOptions: {
external: ['react', 'react-dom'],
output:{
globals: {
react: 'React',
'react-dom': 'ReactDom'
},
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
}
}
}
},
plugins: [RubyPlugin()],
});
I find this Solution, but I can't remove it from the package.json
How can I solve this problem ?
If you are using the vite bundler, you can resolve it with an alias using https://vitejs.dev/config/shared-options.html#resolve-alias
Ex:
resolve: {
alias: [
{
find: /#mui\/material/,
replacement: path.resolve(__dirname, 'node_modules', '#mui', 'material'),
},
],
},

An issue with creating an npm package: 'Cannot find module ...'

I ​recently published an npm module https://www.npmjs.com/package/splashup-widget.
I tried to install it in a 'create-react-app' sample app, but I got an error Cannot find module 'splashup-widget'
this is the webpack config:
var path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve('build'),
filename: 'index.js',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules)/,
use: 'babel-loader'
}
]
},
externals: {
react: "react"
}
}
This is a React code:
import logo from './logo.svg';
import './App.css';
import Quiz from 'splashup-widget'
function App() {
return (
<div className="App">
<Quiz />
</div>
);
}
export default App;
I checked this question: How to build an npm package so it is able to be imported/required
but it seems that it's not my case, since both entry and output filenames are 'index.js'.
Would greatly appreciate any help :-)
The main field in your package's package.json is incorrect; you should change it from index.js to build/index.js.

Unable to load sp-loader for spfx solution with webpack

my typescript file includes the following import:
import { SPComponentLoader } from '#microsoft/sp-loader';
But I get a lot of errors when building with webpack
npx webpack --config webpack.config.js
Here are some of the errors:
ERROR in
./node_modules/#microsoft/sp-loader/lib/requirejs/RequireJsLoader.js
Module not found: Error: Can't resolve './test/RequireJsMock' in
'C:\users\agaskell\source\repos\spfxBanner\node_modules#microsoft\sp-loader\lib\requirejs'
# ./node_modules/#microsoft/sp-loader/lib/requirejs/RequireJsLoader.js
258:14-45 #
./node_modules/#microsoft/sp-loader/lib/requirejs/SPRequireJsComponentLoader.js
# ./node_modules/#microsoft/sp-loader/lib/starter/SPStarter.js #
./node_modules/#microsoft/sp-loader/lib/index.js #
./Classic/client/bootHeader.ts # multi #babel/polyfill
./Classic/client/bootHeader.ts
ERROR in
./node_modules/#microsoft/sp-loader/lib/systemjs/SystemJsLoader.js
Module not found: Error: Can't resolve './test/SystemJsMock' in
'C:\users\agaskell\source\repos\spfxBanner\node_modules#microsoft\sp-loader\lib\systemjs'
I am trying to build my ts file into js for classic SharePoint sites and I normally use gulp for modern pages, but for classic I am using a separate bootloader.ts file and webpack.
Can anyone help?
Here is the webpack.config.js file:
const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: "development",
entry: ['#babel/polyfill',
path.resolve(__dirname, './Classic/client/bootHeader.ts')],
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/
},
{
test: /\.(s*)css$/,
use: [
// fallback to style-loader in development
process.env.NODE_ENV !== "production"
? "style-loader"
: MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
},
{
test: /\.(png|jp(e*)g|svg)$/,
use: [
{
loader: "url-loader",
options: {
limit: 15000, // Convert images < 8kb to base64 strings
name: "images/[hash]-[name].[ext]"
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
resolve: {
extensions: [".tsx", ".ts", ".js"]
},
output: {
filename: "classicBundleAG.js",
path: path.resolve(__dirname, "Classic"),
libraryTarget: "umd"
}
};
I ended up using a workaround for this. I gave up on SPComponentLoader to load my bootstrap and instead installed bootstrap modules locally and then referenced them from my custom sass.
My thoughts are that gulp with yeoman normally handles the SPComponentLoader dependencies, but this time I am using a custom webpack and I did not want to deal with every missing dependency manually.

Using paths in TypeScript in a NodeJS project

I'm trying to use the paths property in tsconfig.json in a NodeJS project.
In tsconfig.json I have something like this:
"baseUrl": ".",
"paths": {
"#myApp/server/*": [
"server/src/*"
],
"#myApp/common/*": [
"common/src/*"
]
},
Running tsc outputs all JS files as expected, but they retain the #myApp... imports. As a result, node won't run as it can't resolve all modules having as path #myApp....
I can't find a way to convert the paths I've set in tsconfig.json to a value that can be used by node. I've only found this question on SO, but it's quite outdated and it does not lead to a clean solution.
Do we have a way to transpile TS to JS in a way in which we are able to use paths?
If anyone out here is using with nodejs and tsconfig-paths. You can use the following commands to make the absolute paths work:
// With ts-node
ts-node -r tsconfig-paths/register src/main.js
// With node
node -r ts-node/register/transpile-only -r tsconfig-paths/register dist/main.js
Got this from here:
https://github.com/dividab/tsconfig-paths/issues/61
Until today I was using tspath as suggested in the accepted answer, but I started to get some issues with relative paths having as baseUrl: '../'.
I switched to a webpack based approach, with this webpack.config.ts config:
import { TsConfigPathsPlugin } from 'awesome-typescript-loader';
import * as fs from 'fs-extra';
import { join } from 'path';
import * as webpack from 'webpack';
const packageConfig = fs.readJSONSync('./package.json', { encoding: 'utf-8' });
const externals = {};
for (const packageName in packageConfig.dependencies)
externals[packageName] = packageName;
const serverConfig: webpack.Configuration = {
entry: {
index: './src/index.ts'
},
resolve: {
extensions: ['.ts', '.js'],
plugins: [
new TsConfigPathsPlugin({ configFileName: 'tsconfig.json' })
]
},
target: 'node',
node: {
__dirname: false
},
externals,
output: {
path: join(__dirname, 'dist'),
filename: '[name].js',
library: '[name]',
libraryTarget: 'umd'
},
module: {
rules: [{
test: /\.ts$/,
loader: 'awesome-typescript-loader'
}]
},
plugins: [
new webpack.BannerPlugin(`Copyright © 2018-${new Date().getFullYear()} BOHR. All rights reserved.`)
],
mode: 'production',
optimization: {
minimize: false
}
};
// tslint:disable-next-line:no-default-export
export default [serverConfig];
Note the imports, you will need to add few packages to use this configuration.
I've found this npm package that converts all absolute paths to relative paths: https://www.npmjs.com/package/tspath.
Running tsc will produce the files with the absolute paths (e.g. #myApp/server/my-library). Then run tspath will convert all paths to the relative path.
Why won't you just use the path module in the code and resolve the path to rest of the directories relative to the one where you started the server from?
Take a look at the line 6 in this example:
https://github.com/Farata/angulartypescript/blob/master/code-samples/Angular6/chapter12/server/rest-server-angular.ts.
The __dirname points at the directory where the server was started from, and public is a subdirectory of this directory. I didn't use the paths option of tsc.

Resources