Skip to content

Commit

Permalink
feat: webpack工作流程以及使用脚手架初始化插件和加载器
Browse files Browse the repository at this point in the history
  • Loading branch information
okbug committed Nov 21, 2021
1 parent 593e24d commit 008afbb
Show file tree
Hide file tree
Showing 30 changed files with 12,572 additions and 1,109 deletions.
12 changes: 12 additions & 0 deletions learnWebpack/webpack-analysis/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "debug webpack",
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}/node_modules/webpack/bin/webpack.js"
}
]
}
34 changes: 33 additions & 1 deletion learnWebpack/webpack-analysis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,36 @@

/2.cjs2esm => commonjs加载esmodule

/3.esm2esm => esm 加载esm
/3.esm2esm => esm 加载esm


[webpack使用脚手架初始化一个plugin或者loader](https://webpack.docschina.org/api/cli/)


# 调试webpack工作流程

使用vscode调试

在项目根目录添加 `.vscode` 文件夹,并且添加配置文件:`launch.json`

```json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "debug webpack",
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}/node_modules/webpack/bin/webpack.js"
}
]
}


```

注意上面`program`的webpack路径要对应自己node_modules下的路径(因为有可能多个版本webpack 导致件夹带上版本号)

然后新建一个文件

17 changes: 17 additions & 0 deletions learnWebpack/webpack-analysis/debugger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const webpack = require('webpack');
const config = require('./webpack.config');



const compiler = webpack(config);
console.log(compiler)
debugger
compiler.run((err, state) => {
console.log(err);
console.log(state.toJson({
assets: true,
chunks: true,
modules: true,
entries: true
}))
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import esmModule from './static-esm-module';

const getLazyModule = () => System.import('./lazy-module');

setTimeout(() => {
getLazyModule.then((modDefault) => {
console.log(modDefault);
});
}, 300);

console.log(esmModule);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'lazy';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'foo';
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const path = require('path');

module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'example_dist'),
filename: '[name].chunk.js',
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'example-loader',
options: {},
},
],
},
],
},
resolveLoader: {
alias: {
'example-loader': require.resolve('../../src/'),
},
},
};
5 changes: 5 additions & 0 deletions learnWebpack/webpack-analysis/my-loader/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"version": "1.0.0",
"description": "webpack loader",
"name": "my-loader"
}
1 change: 1 addition & 0 deletions learnWebpack/webpack-analysis/my-loader/src/cjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./index').default;
25 changes: 25 additions & 0 deletions learnWebpack/webpack-analysis/my-loader/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* See the webpack docs for more information about loaders:
* https://webpack.js.org/contribute/writing-a-loader
*/

module.exports = function loader(source) {
const { loaders, resource, request, version, webpack } = this;
console.log('my-loader');
const newSource = `
/**
* my-loader
*
* Resource Location: ${resource}
* Loaders chained to module: ${JSON.stringify(loaders)}
* Loader API Version: ${version}
* Is this in "webpack mode": ${webpack}
* This is the users request for the module: ${request}
*/
/**
* Original Source From Loader
*/
${source}`;

return newSource;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import foo from "./foo"; // eslint-disable-line

console.log(foo);
21 changes: 21 additions & 0 deletions learnWebpack/webpack-analysis/my-loader/test/functional.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {
runWebpackExampleInMemory,
} from '../test/test-utils';

test('should run with no errors or warnings', async () => {
const buildStats = await runWebpackExampleInMemory('simple');
const { errors, warnings } = buildStats;

expect([...errors, ...warnings].length).toBe(0);
});

test('should append transformations to JavaScript module', async () => {
const buildStats = await runWebpackExampleInMemory('simple');
const { modules } = buildStats;

const moduleToTest = modules[0].source()._source._value;
const loadedString = '* Original Source From Loader';

expect(moduleToTest).toEqual(expect.stringContaining(loadedString));
expect(moduleToTest).toMatchSnapshot();
});
82 changes: 82 additions & 0 deletions learnWebpack/webpack-analysis/my-loader/test/test-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import path from 'path';
import webpack from 'webpack';
import Promise from 'bluebird';
import MemoryFs from 'memory-fs';

const fs = new MemoryFs();
const unitTestFixtures = path.resolve(__dirname, 'fixtures');

/**
*
*
* @param {string} fixtureName
* @param {string} [withQueryString='']
* @returns {string} Absolute path of a file with query that is to be run by a loader.
*/
function getFixtureResource(fixtureName, withQueryString = '') {
return `${getFixture(fixtureName)}?${withQueryString}`;
}

/**
*
*
* @param {string} fixtureName
* @returns {string} Absolute path of a file with query that is to be run by a loader.
*/
function getFixture(fixtureName) {
return path.resolve(unitTestFixtures, `${fixtureName}.js`);
}

/**
*
*
* @param {Object} withOptions - Loader Options
* @returns {{loader: string, options: Object}}
*/
function getLoader(withOptions) {
return [{ loader: path.resolve(__dirname, '../dist/index.js'), options: withOptions }];
}

/**
*
*
* @param {string} exampleName
* @returns {Object|Array} - Returns an object or array of objects representing the webpack configuration options
*/
function getExampleConfig(exampleName) {
return require(`../examples/${exampleName}/webpack.config.js`);
}

/**
*
*
* @param {string} exampleName - name of example inside of examples folder
* @returns
*/
async function runWebpackExampleInMemory(exampleName) {
const webpackConfig = getExampleConfig(exampleName);
const compiler = webpack(webpackConfig);

compiler.outputFileSystem = fs;

const run = Promise.promisify(compiler.run, { context: compiler });
const stats = await run();


const { compilation } = stats;
const { errors, warnings, assets, entrypoints, chunks, modules } = compilation;
const statsJson = stats.toJson();

return {
assets,
entrypoints,
errors,
warnings,
stats,
chunks,
modules,
statsJson,
};
}

export { getExampleConfig, runWebpackExampleInMemory, fs, getFixtureResource, getLoader, getFixture };
32 changes: 32 additions & 0 deletions learnWebpack/webpack-analysis/my-loader/test/unit.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import fs from 'fs';
import Promise from 'bluebird';
import { runLoaders } from 'loader-runner';
import { getFixtureResource, getFixture, getLoader } from './test-utils';

const runLoadersPromise = Promise.promisify(runLoaders);
const readFilePromise = Promise.promisify(fs.readFile, { context: fs });


const loaders = getLoader();

describe('Example Loader Tests: Fixture: simple-file', () => {
const fixtureName = 'simple-file';
const resource = getFixture(fixtureName);

test('loaded file should be different', async () => {
const originalSource = await readFilePromise(resource);
const { result } = await runLoadersPromise({ resource: getFixtureResource(fixtureName), loaders });

expect(result).not.toEqual(originalSource);
});

test('loader prepends correct information', async () => {
const { result } = await runLoadersPromise({ resource: getFixtureResource(fixtureName), loaders });
const resultMatcher = expect.arrayContaining([
expect.stringContaining(' * Original Source From Loader'),
]);

expect(result).toEqual(resultMatcher);
expect(result).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import esmModule from './static-esm-module';

const getLazyModule = () => System.import('./lazy-module');

setTimeout(() => {
getLazyModule.then((modDefault) => {
console.log(modDefault);
});
}, 300);

console.log(esmModule);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'lazy';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'foo';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const path = require('path');
const MyWebpackPlugin = require('../../src/index.js');

module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'example_dist'),
filename: '[name].chunk.js',
},
plugins: [
new MyWebpackPlugin()
]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"version": "1.0.0",
"description": "webpack loader",
"name": "my-webpack-plugin",
"devDependencies": {
"bluebird": "^3.7.2",
"webpack-defaults": "^4.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./index').default;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* See the webpack docs for more information about plugins:
* https://webpack.js.org/contribute/writing-a-plugin/#basic-plugin-architecture
*/

class MyWebpackPlugin {
apply(compiler) {
compiler.hooks.done.tap('MyWebpackPlugin', (
stats /* stats is passed as an argument when done hook is tapped. */
) => {
console.log('Hello World!');
});
}
}

module.exports = MyWebpackPlugin;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import foo from "./foo"; // eslint-disable-line

console.log(foo);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {
runWebpackExampleInMemory,
} from '../test/test-utils';

test('should run with no errors or warnings', async () => {
const buildStats = await runWebpackExampleInMemory('simple');
const { errors, warnings } = buildStats;

expect([...errors, ...warnings].length).toBe(0);
});
Loading

0 comments on commit 008afbb

Please sign in to comment.