├── test ├── cases │ ├── .babelrc │ ├── normal │ │ ├── node_modules │ │ │ ├── a │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── b │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── @d │ │ │ │ └── d │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ ├── c │ │ │ │ └── package.json │ │ │ └── pre-loader │ │ │ │ ├── package.json │ │ │ │ └── index.js │ │ ├── src │ │ │ └── index.js │ │ ├── package.json │ │ └── webpack.config.js │ └── nested │ │ ├── node_modules │ │ ├── a │ │ │ ├── index.js │ │ │ └── package.json │ │ ├── c │ │ │ ├── src │ │ │ │ ├── index.js │ │ │ │ └── main.js │ │ │ └── package.json │ │ └── b │ │ │ ├── node_modules │ │ │ ├── a │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ └── @dd │ │ │ │ └── a │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── index.js │ │ │ └── package.json │ │ ├── package.json │ │ ├── src │ │ └── index.js │ │ └── webpack.config.js └── integration │ ├── normal.js │ └── nested.js ├── .eslintrc.js ├── .editorconfig ├── .travis.yml ├── debug.js ├── lib ├── index.js ├── plugin-webpack5.js ├── util.js ├── plugin-webpack4.js └── plugin.js ├── LICENSE ├── .gitignore ├── package.json └── README.md /test/cases/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /test/cases/normal/node_modules/a/index.js: -------------------------------------------------------------------------------- 1 | export default 'a' -------------------------------------------------------------------------------- /test/cases/normal/node_modules/b/index.js: -------------------------------------------------------------------------------- 1 | export default 'b' -------------------------------------------------------------------------------- /test/cases/nested/node_modules/a/index.js: -------------------------------------------------------------------------------- 1 | export default 'nested a' -------------------------------------------------------------------------------- /test/cases/normal/node_modules/@d/d/index.js: -------------------------------------------------------------------------------- 1 | export default 'd' 2 | -------------------------------------------------------------------------------- /test/cases/nested/node_modules/c/src/index.js: -------------------------------------------------------------------------------- 1 | import {main} from './main' 2 | 3 | export {main} 4 | -------------------------------------------------------------------------------- /test/cases/nested/node_modules/b/node_modules/a/index.js: -------------------------------------------------------------------------------- 1 | const b = `nested inner a` 2 | 3 | export default b -------------------------------------------------------------------------------- /test/cases/nested/node_modules/c/src/main.js: -------------------------------------------------------------------------------- 1 | export const main = function () { 2 | return 'cc' 3 | } 4 | -------------------------------------------------------------------------------- /test/cases/nested/node_modules/b/node_modules/@dd/a/index.js: -------------------------------------------------------------------------------- 1 | const a = '@dd nested inner a' 2 | 3 | export default a 4 | -------------------------------------------------------------------------------- /test/cases/normal/node_modules/c/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "c", 3 | "version": "0.0.1", 4 | "main": "index.js" 5 | } 6 | -------------------------------------------------------------------------------- /test/cases/normal/node_modules/@d/d/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@d/d", 3 | "version": "0.0.1", 4 | "main": "index.js" 5 | } 6 | -------------------------------------------------------------------------------- /test/cases/nested/node_modules/b/node_modules/a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "a", 3 | "version": "0.0.2", 4 | "main": "index.js" 5 | } -------------------------------------------------------------------------------- /test/cases/nested/node_modules/b/index.js: -------------------------------------------------------------------------------- 1 | import a from 'a' 2 | import ddA from '@dd/a' 3 | 4 | export default `nested b, ${a}, ${ddA}` 5 | -------------------------------------------------------------------------------- /test/cases/normal/node_modules/pre-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pre-loader", 3 | "version": "0.0.1", 4 | "main": "index.js" 5 | } 6 | -------------------------------------------------------------------------------- /test/cases/nested/node_modules/a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "a", 3 | "version": "0.0.1", 4 | "main": "index.js", 5 | "postCompile": true 6 | } -------------------------------------------------------------------------------- /test/cases/nested/node_modules/b/node_modules/@dd/a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dd/a", 3 | "version": "0.0.1", 4 | "main": "index.js" 5 | } 6 | -------------------------------------------------------------------------------- /test/cases/normal/node_modules/a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "a", 3 | "version": "0.0.1", 4 | "main": "index.js", 5 | "postCompile": true 6 | } 7 | -------------------------------------------------------------------------------- /test/cases/nested/node_modules/c/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "c", 3 | "version": "0.0.1", 4 | "main": "src/index.js", 5 | "postCompile": "src/*" 6 | } 7 | -------------------------------------------------------------------------------- /test/cases/normal/src/index.js: -------------------------------------------------------------------------------- 1 | import a from 'a' 2 | import b from 'b' 3 | import d from '@d/d' 4 | 5 | export { 6 | a, 7 | b, 8 | d 9 | } 10 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | node: true 4 | }, 5 | parserOptions: { 6 | sourceType: 'module' 7 | }, 8 | extends: 'standard' 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = false 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 2 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | cache: 4 | directories: 5 | - node_modules 6 | node_js: 7 | - "10" 8 | branches: 9 | only: 10 | - master 11 | script: 12 | - npm test 13 | -------------------------------------------------------------------------------- /test/cases/normal/node_modules/b/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "b", 3 | "version": "0.0.1", 4 | "main": "index.js", 5 | "postCompile": true, 6 | "dependencies": { 7 | "a": "0.0.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/cases/nested/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nested", 3 | "version": "0.0.1", 4 | "main": "src/index.js", 5 | "dependencies": { 6 | "a": "0.0.1", 7 | "b": "0.0.1", 8 | "c": "0.0.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/cases/nested/src/index.js: -------------------------------------------------------------------------------- 1 | import a from 'a' 2 | import b from 'b' 3 | import {main} from 'c' 4 | import pkg from '../package.json' 5 | 6 | const c = main() 7 | 8 | export { 9 | a, 10 | b, 11 | c, 12 | pkg 13 | } 14 | -------------------------------------------------------------------------------- /debug.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack') 2 | // var webpackConfig = require('./test/cases/normal/webpack.config') 3 | var webpackConfig = require('./test/cases/nested/webpack.config') 4 | 5 | webpack(webpackConfig, function (err, stats) { 6 | console.log(err, stats) 7 | }) 8 | -------------------------------------------------------------------------------- /test/cases/normal/node_modules/pre-loader/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function (content) { 2 | const fileContext = this.context 3 | if (fileContext.indexOf('node_modules') > -1) { 4 | console.error('未过滤 pre loader') 5 | return new Error('未过滤 pre loader') 6 | } 7 | return content 8 | } 9 | -------------------------------------------------------------------------------- /test/cases/nested/node_modules/b/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "b", 3 | "version": "0.0.1", 4 | "main": "index.js", 5 | "postCompile": true, 6 | "dependencies": { 7 | "a": "0.0.2", 8 | "@dd/a": "0.0.1" 9 | }, 10 | "compileDependencies": [ 11 | "@dd/a", 12 | "a" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /test/cases/normal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "normal", 3 | "version": "0.0.1", 4 | "main": "src/index.js", 5 | "dependencies": { 6 | "a": "0.0.1", 7 | "b": "0.0.1", 8 | "c": "0.0.1", 9 | "@d/d": "0.0.1" 10 | }, 11 | "devDependencies": { 12 | "pre-loader": "0.0.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | let PostCompilePlugin = null 3 | 4 | if (webpack.version && webpack.version[0] > 4) { 5 | // webpack5 and upper 6 | PostCompilePlugin = require('./plugin-webpack5') 7 | } else { 8 | // webpack4 and lower 9 | PostCompilePlugin = require('./plugin-webpack4') 10 | } 11 | 12 | module.exports = PostCompilePlugin 13 | -------------------------------------------------------------------------------- /test/cases/nested/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var PostCompilePlugin = require('../../../lib/index') 3 | 4 | module.exports = { 5 | context: __dirname, 6 | entry: { 7 | app: path.resolve(__dirname, './src/index') 8 | }, 9 | output: { 10 | path: path.resolve(__dirname, './'), 11 | library: 'normal', 12 | libraryTarget: 'umd', 13 | globalObject: 'this' // webpack5 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.js$/, 19 | loader: 'babel-loader', 20 | include: [path.resolve(__dirname, './src')] 21 | } 22 | ] 23 | }, 24 | plugins: [ 25 | new PostCompilePlugin() 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /test/cases/normal/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var PostCompilePlugin = require('../../../lib/index') 3 | 4 | module.exports = { 5 | context: __dirname, 6 | entry: { 7 | app: path.resolve(__dirname, './src/index') 8 | }, 9 | output: { 10 | path: path.resolve(__dirname, './'), 11 | library: 'normal', 12 | libraryTarget: 'umd', 13 | globalObject: 'this' // webpack5 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | enforce: 'pre', 19 | test: /\.js$/, 20 | loader: path.resolve(__dirname, './node_modules/pre-loader'), 21 | include: [path.resolve(__dirname, './src')] 22 | }, 23 | { 24 | test: /\.js$/, 25 | loader: 'babel-loader', 26 | include: [path.resolve(__dirname, './src')] 27 | } 28 | ] 29 | }, 30 | plugins: [ 31 | new PostCompilePlugin({ 32 | compilePaths: [ 33 | 'node_modules/@d' 34 | ] 35 | }) 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /lib/plugin-webpack5.js: -------------------------------------------------------------------------------- 1 | var util = require('./util') 2 | var createPostCompilePlugin = require('./plugin') 3 | 4 | const PostCompilePlugin = createPostCompilePlugin(updateRules) 5 | 6 | function updateRules(compiler, pathsResult, entryPath, callback) { 7 | var ruleSetExec = function(data) { 8 | var ruleSet = data.ruleSet 9 | var _ruleSetExec = ruleSet.exec 10 | var effects = [] 11 | 12 | ruleSet.exec = function (data) { 13 | effects = _ruleSetExec.call(this, data) 14 | 15 | // post compile true 16 | if (pathsResult[data.resource]) { 17 | effects = _ruleSetExec.call(this, Object.assign(data, { 18 | resource: util.modifyPath(data.resource, entryPath) 19 | })).filter(function(r) { 20 | return r.type !== 'use-pre' 21 | }) 22 | } 23 | return effects 24 | } 25 | } 26 | if (compiler.hooks) { 27 | compiler.hooks.normalModuleFactory.tap('PostCompilePlugin', ruleSetExec) 28 | } 29 | callback() 30 | } 31 | 32 | module.exports = PostCompilePlugin 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 doly mood 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var mm = require('micromatch') 3 | 4 | function modifyPath(p, entryPath) { 5 | var basename = path.basename(p) 6 | return path.join(entryPath, basename) 7 | } 8 | 9 | function moduleUsePostCompile(moduleName, flagValue) { 10 | switch (typeof flagValue) { 11 | case 'undefined': 12 | return false 13 | case 'boolean': 14 | return flagValue 15 | case 'string': 16 | if (process.platform === 'win32') { 17 | flagValue = flagValue.replace(/\\/g, '/') 18 | } 19 | return mm.isMatch(moduleName, flagValue, { 20 | matchBase: true 21 | }) 22 | case 'object': 23 | return flagValue.some(glob => 24 | moduleUsePostCompile(moduleName, glob) 25 | ) 26 | } 27 | } 28 | 29 | function isPathMatch(resultPath, includePath) { 30 | for (var i = 0; i < includePath.length; i++) { 31 | if (mm.contains(resultPath, includePath[i].replace(/\\/g, '/'))) { 32 | return true 33 | } 34 | } 35 | return false 36 | } 37 | 38 | function noop() {} 39 | 40 | module.exports = { 41 | modifyPath, 42 | moduleUsePostCompile, 43 | isPathMatch, 44 | noop 45 | } 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | app.js 2 | # Logs 3 | logs 4 | *.log 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | *.pid.lock 14 | 15 | # Directory for instrumented libs generated by jscoverage/JSCover 16 | lib-cov 17 | 18 | # Coverage directory used by tools like istanbul 19 | coverage 20 | 21 | # nyc test coverage 22 | .nyc_output 23 | 24 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 25 | .grunt 26 | 27 | # Bower dependency directory (https://bower.io/) 28 | bower_components 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (http://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules/* 38 | jspm_packages/ 39 | 40 | # Typescript v1 declaration files 41 | typings/ 42 | 43 | # Optional npm cache directory 44 | .npm 45 | 46 | # Optional eslint cache 47 | .eslintcache 48 | 49 | # Optional REPL history 50 | .node_repl_history 51 | 52 | # Output of 'npm pack' 53 | *.tgz 54 | 55 | # Yarn Integrity file 56 | .yarn-integrity 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | .vscode 62 | -------------------------------------------------------------------------------- /lib/plugin-webpack4.js: -------------------------------------------------------------------------------- 1 | var RuleSet = require('webpack/lib/RuleSet') 2 | var util = require('./util') 3 | var createPostCompilePlugin = require('./plugin') 4 | 5 | const PostCompilePlugin = createPostCompilePlugin(updateRules) 6 | 7 | function updateRules (compiler, pathsResult, entryPath, callback) { 8 | var rawRules = compiler.options.module.rules 9 | var ruleSet = new RuleSet(rawRules) 10 | var rules = ruleSet.rules 11 | rules && rules.forEach(function (rule, i) { 12 | updateRule(rule, pathsResult, entryPath) 13 | if (rule.oneOf) { 14 | if (!Array.isArray(rule.oneOf)) { 15 | rule.oneOf = [rule.oneOf] 16 | } 17 | rule.oneOf.forEach(function (rule, i) { 18 | updateRule(rule, pathsResult, entryPath) 19 | }) 20 | } 21 | }) 22 | compiler.options.module.rules = rules 23 | callback() 24 | } 25 | 26 | function updateRule(rule, pathsResult, entryPath) { 27 | if (rule.enforce === 'pre') { 28 | return 29 | } 30 | if (rule.resource) { 31 | var _resource = rule.resource 32 | rule.resource = function (resource) { 33 | // check origional 34 | var ret = _resource.call(this, resource) 35 | if (ret) { 36 | return ret 37 | } 38 | // check dependencies 39 | ret = pathsResult[resource] 40 | if (ret) { 41 | // post compile true 42 | ret = _resource.call(this, util.modifyPath(resource, entryPath)) 43 | } 44 | return !!ret 45 | } 46 | } 47 | } 48 | 49 | module.exports = PostCompilePlugin 50 | -------------------------------------------------------------------------------- /test/integration/normal.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var shell = require('shelljs') 3 | var webpack = require('webpack') 4 | var webpackConfig = require('../cases/normal/webpack.config') 5 | var expect = require('chai').expect 6 | 7 | describe('normal case', function () { 8 | beforeEach(() => { 9 | shell.rm('../cases/normal/app.js') 10 | }) 11 | it('webpack options should be correct', function (done) { 12 | webpack(webpackConfig, function (err, stats) { 13 | var compiler = stats.compilation.compiler 14 | var options = compiler.options 15 | var rule = options.module.rules[0] 16 | if (webpack.version && webpack.version[0] <= 4) { 17 | expect(rule.resource(path.resolve(__dirname, '../cases/normal/index.js'))) 18 | .to.be.false 19 | expect(rule.resource(path.resolve(__dirname, '../cases/normal/src/index.js'))) 20 | .to.be.true 21 | expect(rule.resource(path.resolve(__dirname, '../cases/normal/node_modules/a/index.js'))) 22 | .to.be.true 23 | expect(rule.resource(path.resolve(__dirname, '../cases/normal/node_modules/b/index.js'))) 24 | .to.be.true 25 | expect(rule.resource(path.resolve(__dirname, '../cases/normal/node_modules/m/index.js'))) 26 | .to.be.false 27 | expect(rule.resource(path.resolve(__dirname, '../cases/normal/node_modules/@d/d/index.js'))) 28 | .to.be.true 29 | } 30 | var ret = require('../cases/normal/app.js') 31 | expect(ret.a).to.equal('a') 32 | expect(ret.b).to.equal('b') 33 | expect(ret.d).to.equal('d') 34 | done() 35 | }) 36 | }) 37 | }) 38 | -------------------------------------------------------------------------------- /test/integration/nested.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var shell = require('shelljs') 3 | var webpack = require('webpack') 4 | var webpackConfig = require('../cases/nested/webpack.config') 5 | var expect = require('chai').expect 6 | 7 | describe('nested case', function () { 8 | beforeEach(() => { 9 | shell.rm('../cases/nested/app.js') 10 | }) 11 | it('webpack options should be correct', function (done) { 12 | webpack(webpackConfig, function (err, stats) { 13 | var compiler = stats.compilation.compiler 14 | var options = compiler.options 15 | var rule = options.module.rules[0] 16 | if (webpack.version && webpack.version[0] <= 4) { 17 | expect(rule.resource(path.resolve(__dirname, '../cases/nested/index.js'))) 18 | .to.be.false 19 | expect(rule.resource(path.resolve(__dirname, '../cases/nested/src/index.js'))) 20 | .to.be.true 21 | expect(rule.resource(path.resolve(__dirname, '../cases/nested/node_modules/a/index.js'))) 22 | .to.be.true 23 | expect(rule.resource(path.resolve(__dirname, '../cases/nested/node_modules/b/node_modules/a/index.js'))) 24 | .to.be.true 25 | expect(rule.resource(path.resolve(__dirname, '../cases/nested/node_modules/b/node_modules/@dd/a/index.js'))) 26 | .to.be.true 27 | expect(rule.resource(path.resolve(__dirname, '../cases/nested/node_modules/b/index.js'))) 28 | .to.be.true 29 | expect(rule.resource(path.resolve(__dirname, '../cases/nested/node_modules/cc/index.js'))) 30 | .to.be.false 31 | } 32 | 33 | var ret = require('../cases/nested/app.js') 34 | expect(ret.a).to.equal('nested a') 35 | expect(ret.b).to.equal('nested b, nested inner a, @dd nested inner a') 36 | expect(ret.c).to.equal('cc') 37 | expect(ret.pkg.name).to.equal('nested') 38 | done() 39 | }) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-post-compile-plugin", 3 | "version": "1.2.3", 4 | "description": "A webpack post compile plugin", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "npm run test:integration", 8 | "test:integration": "mocha -t 5000 ./test/integration/*.js", 9 | "lint": "eslint lib/*" 10 | }, 11 | "files": [ 12 | "lib" 13 | ], 14 | "nyc": { 15 | "check-coverage": false, 16 | "lines": 90, 17 | "statements": 90, 18 | "functions": 90, 19 | "branches": 90, 20 | "sourceMap": false, 21 | "include": [ 22 | "lib" 23 | ], 24 | "reporter": [ 25 | "lcov" 26 | ] 27 | }, 28 | "repository": { 29 | "type": "git", 30 | "url": "git+https://github.com/dolymood/webpack-post-compile-plugin.git" 31 | }, 32 | "keywords": [ 33 | "post-complile", 34 | "post", 35 | "compile", 36 | "webpack", 37 | "webpack plugin", 38 | "plugin" 39 | ], 40 | "author": "dolymood", 41 | "license": "MIT", 42 | "bugs": { 43 | "url": "https://github.com/dolymood/webpack-post-compile-plugin/issues" 44 | }, 45 | "homepage": "https://github.com/dolymood/webpack-post-compile-plugin#readme", 46 | "devDependencies": { 47 | "babel": "^6.23.0", 48 | "babel-core": "^6.26.0", 49 | "babel-loader": "^7.1.2", 50 | "babel-preset-es2015": "^6.24.1", 51 | "chai": "^4.1.2", 52 | "codecov": "^3.7.1", 53 | "eslint": "^4.7.2", 54 | "eslint-config-standard": "^10.2.1", 55 | "eslint-plugin-import": "^2.7.0", 56 | "eslint-plugin-node": "^5.1.1", 57 | "eslint-plugin-promise": "^3.5.0", 58 | "eslint-plugin-standard": "^3.0.1", 59 | "json-loader": "^0.5.7", 60 | "mocha": "^3.5.3", 61 | "nyc": "^11.2.1", 62 | "webpack": "^5.36.2" 63 | }, 64 | "peerDependencies": { 65 | "webpack": ">=3" 66 | }, 67 | "dependencies": { 68 | "micromatch": "^4.0.5", 69 | "shelljs": "^0.8.4" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack-post-compile-plugin [![Build Status](https://travis-ci.org/dolymood/webpack-post-compile-plugin.svg?branch=master)](https://travis-ci.org/dolymood/webpack-post-compile-plugin?branch=master) [![codecov.io](http://codecov.io/github/dolymood/webpack-post-compile-plugin/coverage.svg?branch=master)](http://codecov.io/github/dolymood/webpack-post-compile-plugin?branch=master) 2 | 3 | A webpack post compile plugin. It is used to include post compile modules in node_modules. 4 | 5 | ### Install 6 | 7 | ```shell 8 | npm i webpack-post-compile-plugin --save-dev 9 | ``` 10 | 11 | ### Usage 12 | 13 | ```js 14 | const PostCompilePlugin = require('webpack-post-compile-plugin') 15 | const path = require('path') 16 | 17 | module.exports = { 18 | // ... 19 | module: { 20 | rules: [ 21 | // ... 22 | { 23 | test: /\.js$/, 24 | loader: 'babel-loader', 25 | include: [path.resolve(__dirname, './')] 26 | // eg: {"compileDependencies": ["cube-ui"]} // package.json 27 | // the current rule's loader will process node_modules/cube-ui/**/*.js too 28 | } 29 | // ... 30 | ] 31 | }, 32 | plugins: [ 33 | new PostCompilePlugin() 34 | ] 35 | } 36 | ``` 37 | 38 | #### Config 39 | 40 | And if you can control all the packages which you want to post compile, you can just add `postCompile: true` to the **packages** `package.json`: 41 | 42 | ```js 43 | { 44 | "name": "your-one-pkg", 45 | // ... 46 | "postCompile": true 47 | // ... 48 | } 49 | ``` 50 | 51 | 52 | Or you can add `compileDependencies` to your application `package.json`: 53 | 54 | ```js 55 | { 56 | "name": "your-application", 57 | // ... 58 | "compileDependencies": ["xx-pkg"] 59 | } 60 | ``` 61 | 62 | After 1.0.0+, you can alse use `postCompile` like this: 63 | 64 | ```js 65 | { 66 | "name": "your-one-pkg", 67 | // ... 68 | "postCompile": "src/*.js" 69 | // ... 70 | } 71 | ``` 72 | 73 | ```js 74 | { 75 | "name": "your-one-pkg", 76 | // ... 77 | "postCompile": [ 78 | "*.js" 79 | ] 80 | // ... 81 | } 82 | ``` 83 | 84 | 1.0.0+ `postCompile` uses [micromatch](https://github.com/micromatch/micromatch#matching-features) to match the post compile files. 85 | 86 | #### Options 87 | 88 | ```js 89 | new PostCompilePlugin({ 90 | dependenciesKey: 'myCompileDependencies', 91 | compileDependencies: ['a', 'b'], 92 | compilePaths: ['node_module/@test'] 93 | }) 94 | ``` 95 | 96 | * `dependenciesKey {String}` default `'compileDependencies'`, dependencies key in `package.json`, it is used to find and include post compile node modules. 97 | 98 | * `compileDependencies {Array}` default `undefined`, application init post compile node modules, if it is `undefined` then the plugin will get `dependenciesKey` value or `dependencies` keys value in `package.json` as the init application's post complie node modules. 99 | 100 | * `sourceDir {String}` **0.5.1+** default `src`, application source directory, if your application's source directory is `lib` you should set this config to `lib`. 101 | 102 | * `compilePaths {Array}` **1.1.0+** default `undefined`, a dependencies matching any of these conditions will be treated as post compile modules. 103 | -------------------------------------------------------------------------------- /lib/plugin.js: -------------------------------------------------------------------------------- 1 | var util = require('./util') 2 | var path = require('path') 3 | 4 | module.exports = function createPostCompilePlugin (updateRules) { 5 | var defCompileDependenciesKey = 'compileDependencies' 6 | 7 | function PostCompilePlugin (options) { 8 | if (!options) { 9 | options = {} 10 | } 11 | this.key = options.dependenciesKey || defCompileDependenciesKey 12 | this.initDependencies = options.compileDependencies || [] 13 | this.compilePaths = options.compilePaths || [] 14 | this.handledCompilePkgs = {} 15 | this.pathsResult = {} 16 | this.sourceDir = options.sourceDir || 'src' 17 | } 18 | 19 | PostCompilePlugin.prototype.apply = function (compiler) { 20 | var that = this 21 | var called = false 22 | var useHooks = compiler.hooks 23 | 24 | var nmfGetter = function (nmf) { 25 | var resolveResultGetter = function (result, cb) { 26 | if ( 27 | result && 28 | result.descriptionFileData && 29 | result.relativePath && 30 | result.path !== false // setting resolve.alias to false will tell webpack to ignore a module 31 | ) { 32 | // handle compileDependencies 33 | var key = result.descriptionFileData.name + result.descriptionFileData.version 34 | if (!that.handledCompilePkgs[key]) { 35 | that.handledCompilePkgs[key] = true 36 | var compileDependencies = result.descriptionFileData[that.key] 37 | if (compileDependencies) { 38 | compileDependencies.forEach(function (dep) { 39 | if (that.initDependencies.indexOf(dep) === -1) { 40 | that.initDependencies.push(dep) 41 | } 42 | }) 43 | } 44 | } 45 | 46 | var postCompile = result.descriptionFileData.postCompile 47 | if (!postCompile) { 48 | postCompile = that.initDependencies.indexOf(result.descriptionFileData.name) >= 0 49 | } 50 | if (!postCompile) { 51 | postCompile = util.isPathMatch(result.path, that.compilePaths) 52 | } 53 | var usePostCompile = util.moduleUsePostCompile( 54 | result.relativePath, 55 | postCompile 56 | ) 57 | if (usePostCompile && result.path.match(/node_modules/)) { 58 | that.pathsResult[result.path] = true 59 | } 60 | } 61 | cb(null, result) 62 | } 63 | var normalResolverGetter = function (normalResolver) { 64 | if (normalResolver.hooks) { 65 | normalResolver.hooks.result.tapAsync('PostCompilePlugin', function (result, resolveContext, cb) { 66 | resolveResultGetter(result, cb) 67 | }) 68 | } else { 69 | normalResolver.plugin('result', resolveResultGetter) 70 | } 71 | } 72 | 73 | if (nmf.resolveResource) { 74 | var _resolveResource = nmf.resolveResource 75 | nmf.resolveResource = function (contextInfo, context, unresolvedResource, resolver, resolveContext, callback) { 76 | var _callback = function (err, resolvedResource, resolvedResourceResolveData) { 77 | if (err) { 78 | return callback(err, resolvedResource, resolvedResourceResolveData) 79 | } 80 | resolveResultGetter(resolvedResourceResolveData, util.noop) 81 | callback(err, resolvedResource, resolvedResourceResolveData) 82 | } 83 | _resolveResource.call(nmf, contextInfo, context, unresolvedResource, resolver, resolveContext, _callback) 84 | } 85 | } 86 | 87 | if (useHooks) { 88 | nmf.resolverFactory.hooks.resolver.for('normal').tap('PostCompilePlugin', normalResolverGetter) 89 | // normalResolverGetter(nmf.getResolver('normal')) 90 | } else { 91 | normalResolverGetter(nmf.resolvers.normal) 92 | } 93 | } 94 | 95 | if (useHooks) { 96 | compiler.hooks.normalModuleFactory.tap('PostCompilePlugin', nmfGetter) 97 | } else { 98 | compiler.plugin('normal-module-factory', nmfGetter) 99 | } 100 | 101 | var run = function (compiler, callback) { 102 | if (called) return callback() 103 | called = true 104 | /* istanbul ignore if */ 105 | if (compiler.compiler) { 106 | // fix https://github.com/webpack/webpack/pull/5739 107 | compiler = compiler.compiler 108 | } 109 | var entryPath = path.resolve(compiler.options.context, that.sourceDir) 110 | 111 | updateRules(compiler, that.pathsResult, entryPath, callback) 112 | } 113 | if (useHooks) { 114 | compiler.hooks.beforeRun.tapAsync('PostCompilePlugin', run) 115 | compiler.hooks.watchRun.tapAsync('PostCompilePlugin', run) 116 | } else { 117 | compiler.plugin(['before-run', 'watch-run'], run) 118 | } 119 | } 120 | 121 | return PostCompilePlugin 122 | } 123 | --------------------------------------------------------------------------------