I'm trying to create a library with webpack. My main goal is mostly to publish the ES6 module files so that my client applications and import and tree shake the library. (It is meant to be a library of icons, so that users can just bundle the ones they use in their app).
I have the library building the umd module to dist and I've set the module field in the package.json to the src directory file that is exporting all of my icons.
Each icon is a React component. I've imported React and PropTypes to create each one and set them to be externals in the webpack config, however I don't think that matters in this use case because...
I made a test application that npm linked my library and imported one of my icon components from my module. It's definitely going to the source files but my webpack here in my application cannot resolve react and prop-types in those modules. It complains for each in every component.
e.g:
Module not found: Error: Can't resolve 'react' in '/code/svg-icons/src/components'
# ../svg-icons/src/components/AlertIcon.js
# ../svg-icons/src/index.js
# ./src/index.js
I suppose this makes sense, as the AlertIcon module from my library doesn't have a node_module directory to find react.
How do I have other applications provide react, prop-types, and whatever else I want to import in my library's source modules?
For your svg-icons package, you only need to run it through Babel, to transpile it to ES5, that's it.
Your application that depends on svg-icons is the one that will be built with webpack, and it will take care of bundling the imported icons into your app bundle.
There is a great FREE course on the subject by Kent C. Dodds on egghead.io. It will clear everything on the subject for you.
Related
I'm working on an emberjs application that uses several other custom ember addons, one of which we're adding is a new dependency on mathjs (https://mathjs.org/) to do some expression parsing. It isn't clear though what is the correct way to keep the configuration of that dependency on mathjs with only the addon that uses it. Is there a "right" way to do this in ember?
What we ended up doing was just installing the mathjs package into our main app's node_modules, then exposing the library in the browser by doing an app.import('node_modules/mathjs/dist/math.min.js') in our ember-cli-build.js file. This is obviously non-ideal because it means that any app using the custom addon must also do this extra setup to expose this dependency of the addon.
FWIW, we initially tried to just install the mathjs dependency into the addon's node_modules, then we imported it in the component of the addon where it's used. But then the browser said that the mathjs module couldn't be imported from the addon.
You should let ember-auto-import manage this for you. For this:
add math.js to your dependencies of your addon (not devDependencies).
use import syntax to import it in your addon.
For the import syntax you need to be aware that some modules only have a default export which is a object exporting properties while others have individual exports. So its either
import { pi, atan2 } from 'mathjs' or import mathjs from 'mathjs'.
your host app should then have your addon in devDependencies.
Only use app.import syntax if you use something that does not support modules at all.
I am tasked with figuring out how to publish a component library my team is working on. These components will be consumed by various internal applications within the company. I have the following constraints:
The library will be consumed as an npm package from internal local
repository. (this part I have figured out)
Components should be
compiled to JavaScript with typescript interface (*.d.ts) references
within the package.
No third-party packages (including Vue) should
be bundled in. Rather, it’s desirable to have the dependent npm
packages added to a project when the component is added and after npm i.
The compiled css bundle should be included with the package but
should be referenced separately within a project when it’s needed.
The raw scss files that make up the component styles should be
included with the package so they can be bundled into a project’s
existing scss during a build.
I’ve looked into vue-cli-service build --target lib to accomplish this, but it seems that it bundles and packs everything up.
Is what I’m asking even possible? Is it an anti-pattern? Are there alternatives? I don’t know where to begin.
You've headed in the right direction with vue-cli-service build --target lib this is exactly what you need. It bundles your entry .vue file as a component then this bundle becomes your entry point for package.json. It doesn't include the Vue library in it (this is stated in the docs) and I think that by default it's configured to extract the CSS in a separate file in dist folder.
I hope this helps.
We have several websites, each in its own project, and we are looking to migrate them all to using Vue.js. Each website has its own directory with .vue files that are then bundled using Webpack. We have a Webpack config in place that converts the .vue files, bundles, lints and pipes it all through babel and it works fine.
However, now that we have been moving things over for several weeks we have noticed that there are several components and core javascript files that are very similar and ideally we want to pull these out into a shared library of vue components and functions.
We have extracted several .vue into a folder alongside the websites, and put them together as a basic npm module with its own package.json, and include them using an npm file include, so in the package.json it just looks like: "vue-shared": "file:../CommonJavascript/Vue". Now when we try to use Webpack to build the bundle, we get the error:
ERROR in ../CommonJavascript/Vue/index.js
Module build failed (from ./node_modules/eslint-loader/index.js):
Error: Failed to load plugin react: Cannot find module 'eslint-plugin-react'
I'm not sure where this error is coming from, because we aren't using react anywhere, and it seemed happy enough to build fine before we moved the files out. At the moment the only dependency in the shared module is moment, and it only contains 4 .vue, and a basic wrapper to bundle them up:
import button from 'Button.vue'
import loading from 'Loading.vue'
import modal from 'Modal.vue'
import progressBar from 'ProgressBar.vue'
export default {
button,
loading,
modal,
progressBar,
}
But, I was curious so I decided to add the package (even though we don't need it) to see if it would fix the issue, but I then get a new error:
ERROR in ../CommonJavascript/Vue/index.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
ReferenceError: Unknown plugin "transform-runtime" specified in "base" at 0, attempted to resolve relative to "C:\Projects\Tmo\Code\CommonJavascript\Vue"
Now, that one makes a little more sense, we do use the babel runtime transform on the main project, but it isn't required by anything in the shared project and even if it was, surely the fact it is included in the main project means it should still build.
Partly, it seems perhaps I'm just not understanding the way npm resolves dependencies. It seems to be trying to now resolve some dependencies by looking in the shared files project and I dont know why. Also I have no idea where this strange dependency on eslint-plugin-react has come from.
So I guess this is a multi-part question. What is up with the way npm is trying to resolve the dependencies? Am I doing things right by moving the .vue files into a separate project, wrapping it up as a module and requiring it in the main project? and if not, what is the best way to have shared dependencies like this?
This was caused by a mixture of two separate issues:
The import statements didn't reference the file properly, the correct syntax is: import button from './Button.vue' (note the change to file path)
When you add a local package to npm via a path, it creates a symlink to the folder rather than copying the files over (this has been the behaviour since npm v5+). This then changes the way webpack tries to resolve dependencies since it then looks up from the location of the shared files to try and resolve dependencies including thing like eslint and babel.
The eslint-plugin-react dependency was because in visual studio code I had installed the eslint plugin, which it seems had created a .eslintrc file which reference the react plugin in my user folder (c:\users\<username>). Eslint will then use this as the default if it can't find a config file (which it couldn't because it was looking above the shared files because of the pathing issues described above)
We have decided we will be using a git submodule for these files going forward
i am building a tool of my own to trans compile and pack the related js files (that are written in ES6) into a bundle. so far it goes as expected with local files, but when i come to public modules, for example, react and redux etc, it's different. and i am wondering how to include these modules into the bundle? i found that there are always dist folders in most of the public modules with distributed versions residing in. so, are the dist folders always available in any module directory?
Webpack uses the same module resolution as Node.js. node_modules have a package.json which has a main field, that determines which file is being imported when you import the module in your code. Additionally webpack looks for the browser or module fields in package.json and prefers them over main, if they are present. This makes it easy to publish a build that is different from the regular Node.js build (for instance to use ES modules (import/export), which are not supported by yet Node.js but by bundlers like webpack). This behaviour can be configured with the option resolve.mainFields. For an example have a look at the package.json of Redux.
None of these fields are mandatory, but at least main is supposed to be present, so you can simply import a module with:
import module from 'module';
Or with require:
const module = require('module');
Webpack automatically includes the modules you import into the bundle.
The dist directory is not any special, but it's very common to have a dist directory that contains an UMD build. Especially as Unpkg allows you to import a node module without having to publish it manually to a CDN, it uses the dist or umd by default (as described at the bottom of the homepage).
I'm pretty new to some of this stuff and I feel like I must just be missing something simple. I have a very basic Ember.js app that I created with the CLI tool flowing the guide. The code is at https://github.com/nfriedly/particle-webhook-manager
It has a couple of routes and components, and a single third-party dependency, particle-api-js. I installed it twice, via bower and npm, and I'm importing it in one of my components like so:
import particle from 'particle-api-js';
I start up my server with ember serve and it builds successfully. I then open my browser to http://localhost:4200/login where I load the component and it gives me the following error in my console:
Error: Could not find module `particle-api-js` imported from `particle-webhook-manager/components/login-form`
So, my main question is: what am I doing wrong here/how do I make it work?
My secondary question is: why did it "build" successfully and then throw a runtime error for the missing module - shouldn't it have found that in the build stage?
You should not use bower anymore. Use ember browserify to import things installed with npm.
You can import bower modules in your ember-cli-build.js with app.import('bower_components/...js').
You can not import them directly, but you can create a vendor shim to provide this for you. Checkout the ember-cli documentation for this.