Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
webpack-external-import
Advanced tools
import() other chunks and modules from third parties, or other webpack builds themselves! At runtime!
$ yarn add webpack-external-import
This project is under active development
**To jump to the development section click here
npm install webpack-external-import --save
yarn add webpack-external-import
webpack-external-import/webpack
to your webpack plugins:// techblog.webpack.config.js
const URLImportPlugin = require("webpack-external-import/webpack");
{
plugins: [
new URLImportPlugin({
manifestName: "website-one"
})
];
}
// otherblog.webpack.config
const URLImportPlugin = require("webpack-external-import/webpack");
{
plugins: [
new URLImportPlugin({
manifestName: "website-two"
})
];
}
// index.js
import { corsImport } from "webpack-external-import";
import React from "react";
import ReactDOM from "react-dom";
import App from "./App.jsx";
// using Date.now() for cache busting the file. It should only less than 2kb
corsImport(`http://localhost:3002/importManifest.js?${Date.now()}`).then(() => {
ReactDOM.render(<App />, document.getElementById("app"));
});
// you could also use native imports
import(
/* webpackIgnore:true */ `http://localhost:3002/importManifest.js?${Date.now()}`
).then(() => {
ReactDOM.render(<App />, document.getElementById("app"));
});
This plugin works with any Webpack driven application
This assumes a import manifest was loaded somewhere else in the application already.
If you have not imported manifest then wrap your function in another promise:
corsImport("http://localhost:3002/importManifest.js").then(() => {
someFunction();
});
As long as the importManifest
was loaded - this is how it would be used
__webpack_require_.interleaved()
expects a module to contain both the module.id and the namespace
This allows external-import to know where to interleave from.
__webpack_require_.interleaved([namespace]/[module.id])
Below is an example of interleaving a module from website-2
// import a chunk from another website build with webpack-external-import
__webpack_require__.interleaved("website-2/ValidationRules").then(() => {
const validationRules = __webpack_require__("ValidationRules");
// proceed to use as a you would with a normal require statement
validationRules.validateObject(someObject);
});
ExternalComponent
exists for ease of use with React Components and is as SFC using React.Hooks
import { ExternalComponent } from "webpack-external-import";
class SomeComponent extends Component {
render() {
return (
<div>
<ExternalComponent
interleave={__webpack_require__
.interleaved("website-2/TitleComponent")
.then(() => __webpack_require__("TitleComponent"))}
export="Title"
title="Some Heading"
/>
</div>
);
}
}
webpack-external-import
?Use the webpack plugin to inject webpack modules from another build into your build.
Important: Make sure manifestName is unique per webpack build. If you have multiple builds, they all need to have a unique manifestName
webpack.config.js
const URLImportPlugin = require("webpack-external-import/webpack");
{
plugins: [
new URLImportPlugin({
manifestName: "website-one"
})
];
}
Pretend we have two separate apps that each have their independent build. We want to share a module from one of our apps with the other.
To do this, you must add an externalize
object to package.json
.
The externalize
object tells the plugin to make the module accessible through a predictable name.
For example:
// wbsite-two package.json
{
"name": "some-package-name",
"interleave": {
"src/components/Title/index.js": "TitleComponent",
"src/components/hello-world/index.js": "SomeExternalModule"
}
}
// website-one App.js
__webpack_require__
.interleaved("website-3/TitleComponentWithCSSFile")
.then(() => __webpack_require__("TitleComponentWithCSSFile"));
This ensures a easy way for other consumers, teams, engineers to look up what another project or team is willing to allow for interleaving
WEBSITE-ONE app.js
import React, { Component } from "react";
import { ExternalComponent } from "webpack-external-import";
import HelloWorld from "./components/goodbye-world";
import "react-select";
class App extends Component {
constructor(props) {
super(props);
this.state = {
titleUrl: null,
manifestLoaded: false,
loaded: false
};
}
componentDidMount() {
__webpack_require__
.interleaved("website-3/TitleComponentWithCSSFile")
.then(() => __webpack_require__("TitleComponentWithCSSFile"));
}
renderDynamic = () => {
const { loaded } = this.state;
if (!loaded) return null;
return __webpack_require__("SomeExternalModule").default();
};
render() {
return (
<div>
<HelloWorld />
<ExternalComponent
interleave={__webpack_require__
.interleaved("website-2/TitleComponent")
.then(() => __webpack_require__("TitleComponent"))}
export="Title"
module="TitleComponent"
title="Some Heading"
/>
<ExternalComponent
interleave={__webpack_require__
.interleaved("website-3/TitleComponentWithCSSFile")
.then(() => __webpack_require__("TitleComponentWithCSSFile"))}
export="Title"
title="Title Component With CSS File Import"
/>
{this.renderDynamic()}
</div>
);
}
}
Promise.all([
corsImport(`http://localhost:3002/importManifest.js?${Date.now()}`),
corsImport(`http://localhost:3003/importManifest.js?${Date.now()}`)
]).then(() => {
ReactDOM.render(<App />, document.getElementById("app"));
});
WEBSITE-TWO: package.json
{
"name": "website-two",
"version": "0.0.0-development",
"repository": {
"type": "git",
"url": "https://github.com/faceyspacey/remixx.git"
},
"author": "Zack Jackson <zack@ScriptedAlchemy.com> (https://github.com/ScriptedAlchemy)",
"interleave": {
"src/components/Title/index.js": "TitleComponentWithCSSFile",
"src/components/Title/style.css": "TitleComponentWithCSSFileCSS",
"src/components/hello-world/index.js": "SomeExternalModule"
}
}
// Website Two - webpack.config.js
module.exports = {
output: {
publicPath
},
plugins: [
new URLImportPlugin({
manifestName: "website-two",
fileName: "importManifest.js",
basePath: ``,
publicPath: `//localhost:3002/`,
transformExtensions: /^(gz|map)$/i,
writeToFileEmit: false,
seed: null,
filter: null,
debug: true,
map: null,
generate: null,
sort: null
})
]
};
// Website One webpack.config.js
module.exports = {
output: {
publicPath
},
plugins: [
new URLImportPlugin({
manifestName: "website-one",
fileName: "importManifest.js",
basePath: ``,
publicPath: `//localhost:3001/`,
transformExtensions: /^(gz|map)$/i,
writeToFileEmit: false,
seed: null,
filter: null,
debug: true,
map: null,
generate: null,
sort: null
})
]
};
options.fileName
Type: String
Default: manifest.json
The manifest filename in your output directory.
options.publicPath
Type: String
Default: output.publicPath
A path prefix that will be added to values of the manifest.
options.basePath
Type: String
A path prefix for all keys. Useful for including your output path in the manifest.
options.writeToFileEmit
Type: Boolean
Default: false
If set to true
will emit to build folder and memory in combination with webpack-dev-server
options.seed
Type: Object
Default: {}
A cache of key/value pairs to used to seed the manifest. This may include a set of custom key/value pairs to include in your manifest or may be used to combine manifests across compilations in multi-compiler mode. To combine manifests, pass a shared seed object to each compiler's ManifestPlugin instance.
options.filter
Type: Function(FileDescriptor): Boolean
options.test
Type: Function(Object, FileDescriptor): Object
Default: src
Test resource path to see if plugin should apply transformations
options.map
Type: Function(FileDescriptor): FileDescriptor
Modify files details before the manifest is created. FileDescriptor typings
options.sort
Type: Function(FileDescriptor): number
Sort files before they are passed to generate
. FileDescriptor typings
options.generate
Type: Function(Object, FileDescriptor): Object
Default: (seed, files) => files.reduce((manifest, {name, path}) => ({...manifest, [name]: path}), seed)
Create the manifest. It can return anything as long as it's serializable by JSON.stringify
. FileDescriptor typings
options.serialize
Type: Function(Object): string
Default: (manifest) => JSON.stringify(manifest, null, 2)
Output manifest file in a different format then json (i.e., yaml).
React Component
src
: string - a url to a javascript file, note it will need to be built by another webpack build running this plugin
interleave
: function - the __webpack_require__.interleave()
function, which will return a module
export
: string - The named export to use as a component from the module being imported
Each webpack build using the webpack plugin emits a manifest file to the build output directory.
The manifest allows you to find a chunk that you want, even if the name has been hashed.
Below is an example of using the manifest.
In this file, I am importing code from another website/build. My application is loading website two's manifest, which is automatically added to window.entryManifest
under the manifestName
I set in the webpack plugin. After that, I'm importing a chunk from website-two, in this case - the chunk is code-split.
componentDidMount() {
corsImport('http://localhost:3002/importManifest.js').then(() => {
const Title = __webpack_require__
.interleaved("website-two/TitleComponent")
.then(() => __webpack_require__("TitleComponent"))
console.log(Title) // => Module {default: ()=>{}, Title: ()=>{}}
});
}
How to start using the demo In the root directory, run the following
yarn install
yarn demo
from the root directoryThis command will install, all dependencies, build the source for the plugin, install the demo dependencies, run all builds and start serving
How to start the demo in debug mode, using node --inspect and connecting to a chrome debugger
This is mainly for debugging the webpack plugin
In the root directory, run the following
yarn install
yarn demo:debug
from the root directoryNote: localhost:3001 is the "consumer app, while the other is the provider app". Both apps work independently and you should check both of them out (they are extremely basic)
Open chrome dev tools and you should see the box highlighted below appear, click on it to connect to the webpack debugger
FAQs
dynamic import() external urls!
We found that webpack-external-import demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.