I've created my library with npm init svelte and selected Library skeleton project. After writing my component and doing the production build I see in package directory that it is not plain JS because it also contains MyComponent.svelte. I would like my component library to be used by plain JS (or TS) projects. How can I compile it to be pure JS with css and image resources (and *.d.ts)?
If I remember correctly this allows the Svelte compiler to better optimize builds if these files can be used directly. (The package.json has a "svelte" property to identify the entry point for Svelte.)
You probably have to run a separate build process on the resulting package to fully compile everything. The current packaging mechanism (svelte-package) has no options regarding this.
Related
I have three packages inside standard lerna monorepo.
client
react library
core
Core - is a shared component library with some utils (may or may not publish on npm).
React library is component library which will be shared on npm.
client is a bundled js library which will be consumed in browser with static html files.
core is a dependency in react-lib as well as client
Question 1 - How to setup core, should I transpile with tsc and bundle with tools such as rollup or vite (i personally prefer vite/rollup over webpack). or just leave it as is and import it in client and react-lib with absolute paths like 'core/src/*"?
Question 2 - can i build core in 'es' format and build client just like normal react app with either cra or vite. I tried this but i think i am missing something as final bundle doesn't seem to work in browser.
Any help would be really appreciated.
You have a few questions and I might not be able to answer them all but hopefully enough to guide you for the solution you're looking for.
Core - is a shared component library with some utils (may or may not publish on npm).
If you want to use Lerna then I guess you'll have to eventually publish the package on npm or a private repository. As an alternative, you could also use pnpm workspaces and their workspace: protocol which will allow you to link the packages in your workspace (monorepo) without ever downloading them from npm, for example if you use workspace:* then it will always use and link to the latest code from your local workspace. You could also use workspace: protocol with Lerna (or Lerna-Lite) since they both support it.
For your next Questions, I'll answer the last part of your Question 1 first because that affects the other portion of the question.
Question 1: ...or just leave it as is and import it in client and react-lib with absolute paths like 'core/src/*'?
Use absolute paths outside of the package is not a good thing to do since it will only work on your local project and you cannot publish that to npm since it will be broken for the other users. It's better to stick with the workspace and let the package use the main or exports entries defined in your package.json. In other words, it's preferable to always build/transpile and let your other package use the transpiled code and if you need to debug then make sure to also include sourcemap
Question 1: How to setup core, should I transpile with tsc and bundle with tools such as rollup or vite (i personally prefer vite/rollup over webpack)
It probably doesn't matter which one you use TypeScript, Rollup or WebPack, In one of my project I use TypeScript in watch mode, it will auto-transpile whenever you change your code, the downside is that the more packages you have then the more TypeScript threads are opened in watch mode (1x per package) but in your case if you only have 3 then it's fine, there's also this TypeScript issue that I'm following which will hopefully bring multi-threaded compilation in the future. You could also use Rollup and the concept would be the same, use it in watch mode for each package (I've done it with Vite/Rollup using vite build --watch
as explained in the next paragraph).
You can take a look at a project I've done Vue 3 and pnpm workspace using pnpm workspace with the workspace: protocol, it uses Rollup for transpiling and also uses Vite library mode which allows to bundle your library for distribution (on npm or others...), this allows you to bundle each package as a lib that is easily reusable by other projects. It's a Vue 3 project, so it's not a React project but it should give you enough ideas on how to do in React and it should help to answer your Question 2. Also that project is not using Lerna/Lerna-Lite but since it uses the workspace: protocol then it would be super easy to add Lerna on top of it in the future (basically just adding the lerna.json config should be enough)
I created a React component and uploaded it to a private git repo. It's a fairly simple component that renders a data table that can be sorted etc. I used nwb to for the setup / build process (https://github.com/insin/nwb).
It's not published on npm, so when I want to use it on a project I install via something like npm install --save git+ssh://git#github.com/Me/myRepo.git. This all works fine in normal React projects.
Unfortunately on a NextJS site I'm working on, NextJS won't compile, and is giving the error CSS Modules cannot be imported from within node_modules and linking me to https://nextjs.org/docs/messages/css-modules-npm
That page suggests that I might be accidentally using the package's source files - but I'm not. When I look in my /node_modules/myComponent/ folder, there's a /lib/ folder that has the compiled source. However, the styles are still in separate files and are included into the compiled source just like you might normally do (var _defaultModule = _interopRequireDefault(require("./styles/default.module.scss"));).
I did some searching online and it seems like the "quick and easy" solution is to use https://github.com/martpie/next-transpile-modules.
I'd prefer to solve this by fixing my repo though, so that when I install it on a project (whether NextJS or whatever) I get whatever it is that NextJS wants.
So my various questions are:
Is there a way to set up my repo so NextJS is happy with it?
Is nwb not the preferred way to make a React component? Should I have used some other process? I'm not having this problem with any other component, so it seems like this is something I did wrong with my repo.
I've been researching about this topic, many things I read are overlapping with babel, webpack, rollup, and even browserify.
What's the standard way (or most common way) to easily publish source code written in es6 that can be consumed in browser with the script tag and in node with require?
Equally confusing is how many versions are actually needed? I read that there are three - umd, cjs and original source, but isn't umd covering cjs already? And then I also see there's an es version(folder), which I think is identical to the source, why is that needed?
If you are writing a library that supposes to run in the browser & in Node, you have several options:
Bundle it to UMD with rollup (it creates smaller bundles then Webpack, especially recommended for bundling libs).
This solution is the simplest one for you. The downside of it is if your lib allows partial imports (such as lodash allows to import only one function) then your consumers won't be able to do that, they will get your entire bundle.
Publish compiled files as esm + cjs when in package.json you point main field to cjs entry file & module field to the esm entry, in that why your lib consumers will able to import selectively parts of your lib.
The benefit of that option is that your consumers will be able to apply several optimizations to your code, such as tree shaking, module concat etc...
I am new to npm, react and webpack but I have a question. In npm how do you prevent a library from being included production package file?
For example, I am just building a very small component in react and on the site where I am going to place my small component. The problem is Jquery library and bootstrap is already being called in the masterpage of the site and I didn't want to call the same library again in my small application production build but I still want to use them during development(because I am only testing it on local and jquery is not called there). TIA
Appreciate your time ready this and hope I got to learn more from you. By the way I created the app using create-react-app but I already 'ejected' it, so its using the webpack 3
Take a look at Webpack externals
You can have two webpack configs, on the dev config you include the package as normal, but for your production config add externals for jquery, so it uses the global one already on the page
The ability you're looking for is named Code splitting
React loadable may be a good option for you as well
I want to have a project structure like that:
./app/package.json
./app/src/index.js
./widget1/package.json
./widget1/src/index.js
./widget2/package.json
./widget2/src/index.js
./widget3/package.json
./widget3/src/index.js
As you can guess, this project is like an aggregation of NPM widget subprojects, and the app src folder is the real app, that uses the different widget subprojects.
I want a clear and strict separation between the widgets because my current experience shows me that developers tend to introduce unwanted cyclic dependencies between widgets even if I tell them not too.
In practice, all these widgets will be ReactJS widgets that have for most of them 3 common JS libs: React, JQuery and Lodash. Some will not need these 3 libs, some will need an additional lib like packery, react-slick or react-date-picker All these widgets should also share common test libraries like mocha.
They absolutly need to share the exact same common library versions (because obviously I don't want different versions of React in my project nor to increase my bundle size).
For example,
- widget1 could be a DatePicker widget, that depends on React + Lodash + react-date-picker (npm lib, not mine)
- The app project could depend on React + Redux + Normalizr + all the widgets and their transitive dependencies like react-date-picker
All the widgets will be Presentational components and do not need much more fancy dependencies. Some will only depend on React. Some may have a Redux reducer but as it is plain old JS code, there's no dependency needed.
The number of widgets can be quite big and I don't want to edit 200 package.json files on each library update (however I could eventually use some code to handle that).
When inside widget1/src, it should be forbidden to require code from widget2. If a widget had to be able to depend on another widget, this dependency must be set explicitly in package.json of the client widget.
I should be able to build with Webpack and test all the widgets independently. I should also be able to build and test at once the whole project, including all the subprojects, and having a single aggregated global test and code coverage report.
I don't want it to have a bad developer experience. React and Webpack permits to have Hot code reloading. If I have the real app in my browser and I modify code of a widget, I should be able to see the change live with react-hot-loader and not have to run npm commands nor hit F5.
What I look for is the equivalent of Java Maven's dependencyManagement system where you usually set versions for all your subprojects in parent POM, and versions are somehow inherited to all child projects. All child projects cannot see each others (unless explicit dependency is added), but they can say they depend on a library declared in parent project. All the lib version numbers can be set in the parent project.
Is it possible to do so with NPM and Webpack?
Or at least something close to it?
Thanks
You could put each widget in it's own git repo and install them with NPM via the repo URL. As long as each widget defines the libraries they use in their own NPM package, when they're used in the main project NPM will handle all of the dependencies for you.
Depending on the size of your team you could also sign up for NPM's private packages and host them there https://www.npmjs.com/npm/private-packages
You might want to try https://github.com/n8tz/layer-pack,
as it meets many of the needs mentioned
It allows to:
inherit several npm packages in 1 source tree
manage module inheritance ( drive node & webpack to resolve them well )
put all Webpack conf & profiles in a shared, inheritable and versioned package
etc...
Note that hot reloading with too many inherited packages can be slow.
Alternative is to use precompiled versions of your widgets & externalize theirs deps.