Creating a standalone web component build using as an IIFE - javascript

I have create a web component for displaying gists generally in any html content.
I used the Lit Element Typescript Starter Project as a baseline and it comes with a rollup.config.js file.
I changed the output format to iife and left the rest the same, with exception of the component and bundle names. The reason I did this is that I wanted the bundle to be easily accessible via script tags, and rollup says that the iife format does this.
This is the modified rollup.config.js file.
// ============================================
// The configuration is based on the rollup starter
// app found here:
//
// https://github.com/rollup/rollup-starter-app/blob/master/package.json
//
// This project is based
// ============================================
/**
* #license
* Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at
* http://polymer.github.io/LICENSE.txt
* The complete set of authors may be found at
* http://polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at
* http://polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at
* http://polymer.github.io/PATENTS.txt
*/
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import {terser} from 'rollup-plugin-terser';
import replace from '#rollup/plugin-replace';
import filesize from 'rollup-plugin-filesize';
// `npm run build` -> `production` is true
// `npm run dev` -> `production` is false
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'fs-gist.js',
output: {
file: 'fs-gist.bundle.js',
format: 'iife', // immediately-invoked function expression — suitable for <script> tags
sourcemap: true,
},
onwarn(warning) {
if (warning.code !== 'THIS_IS_UNDEFINED') {
console.error(`(!) ${warning.message}`);
}
},
plugins: [
replace({'Reflect.decorate': 'undefined'}),
resolve(), // tells Rollup how to find date-fns in node_modules
commonjs(), // converts date-fns to ES modules
production && terser({
module: true,
warnings: true,
mangle: {
properties: {
regex: /^__/,
},
},
}),
filesize({
showBrotliSize: true,
})
],
};
The build seems to be working fine. There's a demo here:
https://stackblitz.com/edit/typescript-fs-gist?file=index.ts
Just curious if anyone knows whether any of the other rollup settings should be tweaked or changed since I changed the format to iife from esm?

Rollup configs really depend on what you want to do. If it works currently for what you want to do, then that's great and nothing needs to be changed.
Since it's a config file, if it's not working, everything else is up to you and what you want out of it. For example, maybe if you want to make it work on older browsers, you would use the plugin #rollup/plugin-babel to transpile your code. If you want to offer it as umd and es, you could add those to the build steps.
The rollup documentation is pretty extensive, and you should look through what's possible: https://rollupjs.org/guide/en/
Once you have a better idea of your project's needs, you can search through the docs for examples of how to add specific plugins, steps, etc.

Related

Next.js (React) - Can't import local typescript file into config file

Situation
I would like to run some Database code (mongoDB(mongoose)) on server startup / during builds. Considering next js doesn't have any lifecycle hooks that you can hook into in an easy manner, I was trying to perform the database actions in my webpack (next.config.mjs) configuration. However I ran into some problems with importing local files.
Current setup
This is the code of my current next.config.mjs file. (PS. I have also tried the CommonJS way of requiring the needed files, but that also fails with error meessage "module not found".)
None of the lines that import a local typescript file appear to succeed and I have checked the paths multiple times. They always end up with the error message "ERR_MODULE_NOT_FOUND". Only if a node_module package is imported, it works as expected (the mongoose npm package).
Code
/** #type {import('next').NextConfig} */
const { EmployeesSchema } = await import("./mongodb_schemas/employee_schema");
import { EmployeesSchema } from "./mongodb_schemas/employee_schema";
import "./util/test"
import mongoose from "mongoose";
const nextConfig = {
experimental: {
externalDir: true,
},
reactStrictMode: true,
swcMinify: true,
images: {
domains: ["*", "**", "www.google.com"],
},
webpack: (
config,
{ buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
) => {
if (isServer) {
console.log(process.cwd());
}
return config;
},
};
export default nextConfig;
Anyone got a clue to why this might end up happening / have any possible solutions to the problem? I have also tried with a normal JavaScript file instead of a Typescript file, which also didn't work. I have found some similar asked questions on Stack Overflow but which were all left unanswered.
My guess for the reason why this occurs: during the build of the project, so when "npm run dev" is ran, the next.config.mjs is copied to a different location into the file structure, which means that the relative paths aren't correct anymore and thus the files can't be found.
PS. My apologize if the question is unclear / in an unusual format, it is my first post so not used to it.

How to use node modules outside of webpack encore files?

I have started using webpack encore in my Symfony 5 web app and still haven't figured it all out.
I'd like to use node modules outside of webpack encore files but I can't find a way of doing this.
For example I have installed Datatables and I'd like to use it in a JavaScript file inside the public/assets/js directory, but when I try I get $(...).DataTable is not a function.
In my app.js I do import all the modules I need :
import 'select2';
import 'parsleyjs';
import 'datatables';
Here is my webpack.config.js :
const Encore = require('#symfony/webpack-encore');
// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
*/
.addEntry('app', './assets/app.js')
// enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js)
.enableStimulusBridge('./assets/controllers.json')
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
.splitEntryChunks()
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
// .enableSingleRuntimeChunk()
.disableSingleRuntimeChunk()
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
.configureBabel((config) => {
config.plugins.push('#babel/plugin-proposal-class-properties');
})
// enables #babel/preset-env polyfills
.configureBabelPresetEnv((config) => {
config.useBuiltIns = 'usage';
config.corejs = 3;
})
// enables Sass/SCSS support
//.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment if you use React
//.enableReactPreset()
// uncomment to get integrity="..." attributes on your script & link tags
// requires WebpackEncoreBundle 1.4 or higher
//.enableIntegrityHashes(Encore.isProduction())
// uncomment if you're having problems with a jQuery plugin
.autoProvidejQuery()
;
module.exports = Encore.getWebpackConfig();

Node.js require a file relative to the root of the package

In Node.js, is there any way to require file from the same package without using relative paths? For example, here's a snippet of code from ESLint.
const rule = require("../../../lib/rules/accessor-pairs"),
{ RuleTester } = require("../../../lib/rule-tester");
The fact that we have to walk all the way up the tree ../../../ to get to the root is not only annoying. It's also brittle, because I can't move the code without updating all of dependency references.
Yet somehow Node.js developers seem to have lived with it the past 10 years. I can't find anything in the docs or Stack Overflow that solves this problem other than a third-party dependency called require-self. Nor have I been able to find a definitive statement that using relative paths is the only non-hacky way for a file to require another file in the same module.
If there's a way to specify a path relative to the package root in ECMAScript Modules (ESM) but not CommonJS (CJS), or vice versa, I would like to know that as well.
To be clear, I don't think there is a solution to the problem. If there is great. Otherwise, I'm looking for confirmation with an authoritative reference.
Not necessarily the same package - if you are writing libraries this won't be useful, but if you are writing the "final application" - the thing that actually gets run:
One option:
If the NODE_PATH environment variable is set to a colon-delimited list of absolute paths, then Node.js will search those paths for modules if they are not found elsewhere.
So you can do any of:
1.
export NODE_PATH=.
node app.js
NODE_PATH=. node app.js
// app.js (or whatever your entry point is) before *any* require() calls
process.env.NODE_PATH = __dirname;
require('module').Module._initPaths();
Or, another way:
The Module object representing the entry script loaded when the Node.js process launched.
https://nodejs.org/api/modules.html#modules_require_main
So you can just do:
const rule = require.main.require("./lib/rules/accessor-pairs")
anytime you want it to be relative to the root (assuming that is how you have your project structured).
You can use the package name itself as a "symlink" to the package root.
Example - foo package imports bar script relative to the foo package root.
package.json
{
"dependencies": {
"foo": "file:./foo"
}
}
index.js
const foo = require('foo');
console.log(foo.bar); // prints "hello"
foo/index.js
const bar = require('foo/bar'); // import relative to the package root
module.exports = {
bar: bar
}
foo/bar.js
module.exports = 'hello';
If you use vscode then you're in luck - !!!! jsconfig.json in project root handles this masterfully for commonjs, es6, amd, umd, etc
The jsconfig.json file specifies the root files and the options for the features provided by the JavaScript language service.
jsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"baseUrl": ".",
"paths": {
"#rules/*": ["path/to/lib/rules/"]
}
}
}
and then to use the alias:
const rule = require('#rules/accessor-pairs'),
{ RuleTester } = require('#rules/rule-tester');
Read more:
https://code.visualstudio.com/docs/languages/jsconfig

How does webpack-encore works with symfony 5?

I'm getting a bit mad dealing with webpack-encore in a symfony 5 project.
There is few things i just don't understand. first of all here is my webpack.config.js :
const Encore = require('#symfony/webpack-encore');
// Manually configure the runtime environment if not already configured yet by the "encore"
command.
// It's useful when you use tools that rely on webpack.config.js file.
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
*/
.addEntry('app', './assets/app.js')
// enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js)
.enableStimulusBridge('./assets/controllers.json')
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
.splitEntryChunks()
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
.configureBabel((config) => {
config.plugins.push('#babel/plugin-proposal-class-properties');
})
// enables #babel/preset-env polyfills
.configureBabelPresetEnv((config) => {
config.useBuiltIns = 'usage';
config.corejs = 3;
})
// enables Sass/SCSS support
//.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment if you use React
//.enableReactPreset()
// uncomment to get integrity="..." attributes on your script & link tags
// requires WebpackEncoreBundle 1.4 or higher
//.enableIntegrityHashes(Encore.isProduction())
// uncomment if you're having problems with a jQuery plugin
//.autoProvidejQuery();
module.exports = Encore.getWebpackConfig();
The thing is when i use {{ asset('build/images/my-image.png') }} in my template the file is not found though it is in assets/images/my-image.png
How should i access my image???
Why it is not in manifest.json ??
Why am i not having images in my public/build/ folder ?
What path should i be using to reference my image in app.css as a background-image for example ?
This thing is a nightmare to use & configure.....
Thanks in advance
Thank you guys you are both right,
.copyFiles({
from: './assets/images',
// optional target path, relative to the output dir
to: 'images/[path][name].[ext]',
// if versioning is enabled, add the file hash too
//to: 'images/[path][name].[hash:8].[ext]',
// only copy files matching this pattern
//pattern: /\.(png|jpg|jpeg)$/
})
this part was missing in my config files, then i did not run the build command.....
But it still not an easy tool.
Have a good day.
you tryed run command for build files npm run build ?
or run command for recompile automatically assets
how of documentation exemple
https://symfony.com/doc/current/frontend/encore/simple-example.html

Vue: How to build bundle for Nuxt with vue-cli-service?

A user tries to use my package for nuxt.js, but gets the error: document is not defined.
I found the first issue. When I build the bundle with "build-bundle": "vue-cli-service build --target lib --name index ./src/index.js",
vue-style-loader is being used. This, however, results in the error for using nuxt projects. This part is failing:
function addStyle (obj /* StyleObjectPart */) {
var update, remove
var styleElement = document.querySelector('style[' + ssrIdKey + '~="' + obj.id + '"]')
Document is not defined since we are using server rendering. But the question is how can I build up my package so that I can use it with nuxt?
I need:
index.common.js
index.umd.js
index.umd.min.js
This is due to the server-side rendering. If you need to specify that you want to import a resource only on the client-side, you need to use the process.client variable.
For example, in your .vue file:
if (process.client) {
require('external_library')
// do something
}
The above is the fundamental solution to document is not defined.
I checked some information and found that, this problem is not caused by your package. In fact, the problem lies on the cache-loader package in the user’s nuxt project.
For some reason cache-loader incorrectly determined the current environment as browser and not node so that vue-style-loader is confused and used client implementation instead.
So try to let users add the following configuration to the nuxt.config.js file to disable stylesheet caches on server-side:
build: {
...
cache: true,
extend(config, { isServer, isDev, isClient }) {
...
if (isServer) {
for (const rules of config.module.rules.filter(({ test }) =>
/\.((c|le|sa|sc)ss|styl.*)/.test(test.toString())
)) {
for (const rule of rules.oneOf || []) {
rule.use = rule.use.filter(
({ loader }) => loader !== 'cache-loader'
)
}
}
}
...
}
...
}
I found a solution but it is not using the vue-cli service. Instead, the files are compiled by rollup. I found using the cli service much easier. The only problem with the cli service is it will adjust the "flow" of your repo. However, you can modify the rollup.config.js to amend the folder structure.
The problem with rollup is that it isn't webpack. Therefore, all components using a webpack configuration need to be adjusted or rollup.config.js needs to be amended to include the additional functionality

Categories