Vite Vue 3 library build doesn't implicitly include dist/style.css - javascript

I built a library project (Vue 3, Vite) and I want to include it in a host project via package.json.
But I faced a problem where I can import the components and run a simple programme with those imported components but their styles are gone.
Please let me know what is wrong with my config. It doesn't make sense when I have to manually import css into my host project.
Just to clarify, I don't have any .css source files in my project. style.css was compiled from my *.vue components
This is the vite.config.ts for my library project. Everything that I need exported is in src/.
// Library project
import { defineConfig } from "vite"
import vue from "#vitejs/plugin-vue"
import typescript from '#rollup/plugin-typescript';
const path = require("path")
// https://vitejs.dev/config/
export default defineConfig( {
plugins: [{
...typescript( { tsconfig: "./tsconfig.json" } ),
apply: "build",
declaration: true,
declarationDir: "types/",
rootDir: "/",
}, vue()],
resolve: { alias: { "#": path.resolve(__dirname, "./src") } },
build: {
lib: {
entry: path.resolve(__dirname, "src/index.ts"),
name: "gsd-vue-egui",
// fileName: (format) => `gsd-vue-egui.${format}.js`,
},
rollupOptions: {
external: ["vue"],
output: {
// Provide global variables to use in the UMD build
// Add external deps here
globals: { vue: "Vue" },
},
},
},
server: {
port: 30001,
}
} )
And this is the relevant part of my package.json
{
"name": "gsd-vue-egui",
"private": true,
"version": "0.0.0",
"scripts": {
"preinstall": "npx npm-force-resolutions",
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
"test": "npm run test:unit",
"test:unit": "jest --config=jest.config.js test",
"lint:css": "stylelint --formatter verbose --config .stylelintrc \".\" --fix",
"lint:eslint": "eslint --ext js,vue,ts \".\" --fix",
"lint": "npm run lint:css && npm run lint:eslint"
},
...
}
The structure of my dist/ folder after running npm run build is as follows:
dist/
|-components/
| |-Button.vue.d.ts
|-App.vue.d.ts
|-MyLibraryName.es.js
|-MyLibraryName.umd.js
|-index.d.ts
|-main.d.ts
|-style.css

You need to manually import your CSS because you are shipping JS and CSS files independently in your package. If you don't want to manually import your CSS, you need to package your SFC files for npm. This is the document for Vue 2, but its idea can totally apply to Vue 3.
Here are some points to note:
You must ship your .vue files along with your npm package by NOT adding the /src folder to the .npmignore file
In your host project, import your .vue file directly from your package import YourComponent from 'your-package/src/your-component.vue'
This approach will not work for anyone who wishes to use the component directly in a browser via the <script> tag, anyone who uses a runtime-only build or build processes which don’t understand what to do with .vue files
Some components might provide side effects like directives, or extend other libraries with additional functionality
Manually importing CSS files will never be a bad idea and almost all the Vue packages I know use that approach

Related

Moving nuxt 3 to JavaScript from TypeScript

When getting started with nuxt 3, it creates TypeScript project by default.
Is there a way to move to JavaScript?
I have tried:
Rename nuxt.config.ts to nuxt.config.js
delete tsconfig.json
add jsconfig.json
Contents of nuxt.config.js
export default {
};
contents of package.json
{
"private": true,
"scripts": {
"dev": "nuxi dev",
"build": "nuxi build",
"start": "node .output/server/index.mjs"
},
"devDependencies": {
"nuxt3": "latest"
}
}
Still the .nuxt folder creates TypeScript files
No, unfortunately in the current nuxt3 version (3.0.0-27268729.5b8e10f), there is no configuration to disable the output of those type declaration files.
While the generated .d.ts file are intended to help TypeScript developers, Nuxt does not require app source to be written in TypeScript. The .d.ts files should have no impact on your JavaScript development other than the slight delay in generating those files.

Read the consumer package.json from a package built using webpack in prepare script

I have a library that uses webpack to be bundled, I need to read the consumer package.json config passed to the library.
I tried:
externals: [
{
'global-package': path.resolve(__dirname, '/../../../package.json')
}
]
The library package.json scripts section is like this:
"scripts": {
"prepare": "webpack --mode=production"
}
But when I try to install the package by installing the consumer app, It consider the external path in:
/home/user/.npm
Can you tell me how can I achieve that please?

Relative references must start with either "/", "./", or "../"

I am newbie to lit-element, and when use import to include the library, I am getting error as:
Uncaught TypeError: Failed to resolve module specifier "lit-element".
Relative references must start with either "/", "./", or "../".
Please provide any alternatives/solutions.
import { LitElement, html } from 'lit-element';
class MyElement extends LitElement {
render(){
return html`
<div>
<p>A paragraph</p>
</div>
`;
}
}
customElements.define('my-element', MyElement);
This doesn't work because js imports must reference a specific file with either a relative path or an absolute path, assuming your project structure is something like the following:
/node_modules
/lit-element
/other-library
/src
/components
my-element.js
index.html
From my-element.js, your import would be
import {LitElement, html} from '../../node_modules/lit-element/lit-element.js'
However, since this kind of configuration is confusing and you'll probably end up setting a build script sometime too, the recommendation would be to keep your imports as they are right now and use a dev server that remaps your imports to node_modules like open-wc's web server
Update (Feb. 2021): The web server mentioned on this question has gone through a few iterations and improvements. The current package is #web/dev-server
As you probably know, this type of import is known as 'bare import':
import { LitElement, html } from 'lit-element';
And the error happens because web browsers cannot resolve bare imports by themselves.
I don't know what webserver are you using for developing, but a good way of avoid this type of warnings is choose one that could manage this type of imports, for example web-dev-server
There are other approaches, using, for example tools like Webpack, Polymer-cli, Open Web Components, etc, as this article explains, but, IMO, the web-dev-server option is a very good one for start.
I tried webpack for this issue and that works fine for me.
Here is how I set up webpack on my node javascript project.
First, you need to install the following packages on your project
npm install --save-dev webpack
npm install --save-dev html-webpack-plugin
npm install --save-dev css-loader
npm install --save-dev style-loader
Then, you have to create webpack.config.cjs on your project root and paste the following code into it. (please change file paths as your file structure)
const path = require('path');
const HtmlWebpack = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
},
plugins:[
new HtmlWebpack({
template:path.resolve(__dirname,'./src/template/index.html')
})
],
module:{
rules:[
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource"
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
]
},
devServer:{
port:8080,
hot: true,
static: {
directory: path.join(__dirname, 'dist'),
},
compress: true,
client: {
progress: true,
},
}
}
then add this line to your package.json file
"scripts": {
"build": "webpack",
"dev": "webpack-dev-server --open",
},
now open a terminal on your project root and run npm run dev on it.
You can serve bare module imports with polimer-cli.
a. install it: npm install --save-dev polymer-cli
b. Create polymer.json in your project with roughly contens:
{
"entrypoint": "index.html",
"shell": "app.js",
"npm": true
}
c. do polymer serve

Tell Webpack Where to Find Static Assets in Vue Application

I recently switched to the Vue 3 CLI. After using creating a Vue project I installed webpack and then added the following file to my project's base directory:
vue.config.js
const webpack = require('webpack')
module.exports = {
configureWebpack: {
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
]
},
chainWebpack:
config => {
config.optimization.delete('splitChunks')
}
}
My goal is to make custom elements using this great module: https://github.com/karol-f/vue-custom-element. It seems to work as intended, but when I run npm run build, all hrefs in my index.html file link to the root directory (href=/css/app.11f77a6e.css), so the browser looks in places like:
`file:///C:/css/app.11f77a6e.css`
How can I configure Webpack so that links to resources are relative and looked for in the dist folder?
I've tried adding a webpack.config.js file to my project's root with the following:
const path = require('path');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist')
}
}
But it didn't help.
Here's my package.json
{
"name": "build-flow",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"vue": "^2.5.21",
"vue-custom-element": "^3.2.6",
"webpack": "^4.28.4"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^3.3.0",
"#vue/cli-service": "^3.3.0",
"vue-template-compiler": "^2.5.21"
}
}
Seeing file:/// URLs implies that you're not viewing the files through a dev server. You're probably opening up index.html directly (e.g., by double-clicking index.html). If that's the case, you need to start up a server in dist, and navigate to it from your browser:
Open a Terminal, and CD into <project_root>/dist.
Run python -m SimpleHTTPServer, which should print out something like Serving on 0.0.0.0 port 8000. Make note of the port number for the next step. (Alternatively, run http-server)
Open a browser, and navigate to http://localhost:8000.

How to create single page web application with typescript and webpack?

I have been creating single page applications in Angular for some time, and now I would like to create a single page application but without using the entire framework.
I would like to have one .html file, and one javascript file, which would be compiled typescript file, say index.ts. And inside index.ts I would import things from other typescript files.
Are there any projects online which are similar to what I want to achive, and is it possible to setup npm project like this at all?
Edit:
After some time, this is what I accomplished:
My project structure:
├── bundle.js
├── functions.ts
├── index.html
├── index.ts
├── package.json
├── style.css
├── tsconfig.json
└── webpack.config.js
package.json
{
"name": "rxjs6-demo",
"version": "1.0.0",
"main": "index.ts",
"scripts": {
"start": "webpack-dev-server --open"
},
"devDependencies": {
"ts-loader": "^5.3.1",
"typescript": "^3.2.2",
"webpack": "^4.27.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
},
"dependencies": {
"rxjs": "^6.4.0"
}
}
tsconfig.json
{
"compilerOptions": {
"outDir": ".",
"noImplicitAny": false,
"sourceMap": true,
"module": "es6",
"target": "es6",
"allowJs": true
},
"include": ["*.ts"],
"exclude": []
}
webpack.config.json
module.exports = {
entry: './index.ts',
output: {
filename: 'bundle.js'
},
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: '.'
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ]
}
};
index.html
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="bundle.js"></script>
</body>
</html>
running npm start will start a webpack-dev-server which recompiles my application each time any typescript file changes. Inside index.ts I can import stuff from other .ts files. But what I couldn't accomplish is making webpack-dev-server reload my app in the browser when html or css files change.
Any help or general suggestions about the structure of my application will be greatly appreciated.
With the current setup, Webpack is not processing your .html and .css files, so it stands to reason that it's also not monitoring them for changes. Rather than adding link tags into your .html file for the .css files, you can instruct Webpack to process the .css files using css-loader and style-loader.
First, you need to install css-loader and style-loader. e.g.:
npm i -D css-loader style-loader
css-loader is responsible for processing CSS files and style-loader is responsible for injecting them into the DOM. When using this approach, the output bundle.js (in your example) will contain the transpiled JavaScript and the CSS, with the CSS itself being wrapped up in JavaScript and DOM manipulation.
Next, you need to add a rule to webpack.config.js:
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
This rule, which sits in the rules array alongside your existing ts-loader rule, instructs Webpack to process .css files first using css-loader and then style-loader.
Lastly, you can add an import into your index.ts file:
import './style.css';
That should be all that's needed for Webpack to start processing and monitoring your .css file. For additional files, you can add more import statements as shown above.
As for .html files, there's a good answer for that here that should help. There's also a great tutorial/online book on the styling topic (and almost everything else you could need) by SurviveJS here. The book also covers things like building for production, which allows for extracting the CSS content out into a separate file for production builds, etc.

Categories

Resources