Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: vuejs/vue-loader
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v16.0.0-beta.8
Choose a base ref
...
head repository: vuejs/vue-loader
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v16.0.0-beta.9
Choose a head ref
  • 11 commits
  • 38 files changed
  • 3 contributors

Commits on Sep 24, 2020

  1. Copy the full SHA
    bd9a737 View commit details

Commits on Sep 25, 2020

  1. Copy the full SHA
    0ca3001 View commit details

Commits on Oct 22, 2020

  1. Copy the full SHA
    c5adb71 View commit details
  2. Copy the full SHA
    cfadb7a View commit details
  3. test: add todos

    haoqunjiang committed Oct 22, 2020
    Copy the full SHA
    a56585e View commit details

Commits on Oct 23, 2020

  1. Copy the full SHA
    ded8d0e View commit details
  2. chore: fix type errors

    haoqunjiang committed Oct 23, 2020
    Copy the full SHA
    2e98ea6 View commit details

Commits on Oct 26, 2020

  1. Copy the full SHA
    4b9b26c View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    859a45d View commit details

Commits on Oct 27, 2020

  1. fix: fix mini-css-extract-plugin missing default export error (#1749)

    Default exports should only be used for CSS modules.
    thecrypticace authored Oct 27, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    55c6b12 View commit details
  2. 16.0.0-beta.9

    haoqunjiang committed Oct 27, 2020
    Copy the full SHA
    64be762 View commit details
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-loader",
"version": "16.0.0-beta.8",
"version": "16.0.0-beta.9",
"license": "MIT",
"author": "Evan You",
"main": "dist/index.js",
@@ -53,16 +53,20 @@
"jest": "^26.4.1",
"jsdom": "^16.4.0",
"lint-staged": "^10.3.0",
"markdown-loader": "^6.0.0",
"memfs": "^3.1.2",
"mini-css-extract-plugin": "^0.11.2",
"normalize-newline": "^3.0.0",
"null-loader": "^4.0.1",
"prettier": "^2.1.1",
"pug": "^2.0.0",
"pug-plain-loader": "^1.0.0",
"source-map": "^0.6.1",
"style-loader": "^1.2.1",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"ts-jest": "^26.2.0",
"ts-loader": "^8.0.6",
"typescript": "^4.0.2",
"url-loader": "^4.1.0",
"vue": "^3.0.0-rc.10",
@@ -74,6 +78,7 @@
},
"jest": {
"preset": "ts-jest",
"testTimeout": 10000,
"testEnvironment": "node",
"testPathIgnorePatterns": [
"<rootDir>/dist/",
8 changes: 6 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -116,7 +116,11 @@ export default function loader(
.relative(rootContext || process.cwd(), resourcePath)
.replace(/^(\.\.[\/\\])+/, '')
const shortFilePath = rawShortFilePath.replace(/\\/g, '/') + resourceQuery
const id = hash(isProduction ? shortFilePath + '\n' + source : shortFilePath)
const id = hash(
isProduction
? shortFilePath + '\n' + source.replace(/\r\n/g, '\n')
: shortFilePath
)

// feature information
const hasScoped = descriptor.styles.some((s) => s.scoped)
@@ -159,7 +163,7 @@ export default function loader(
const scopedQuery = hasScoped ? `&scoped=true` : ``
const attrsQuery = attrsToQuery(descriptor.template.attrs)
const bindingsQuery = script
? `&bindings=${JSON.stringify(script.bindings)}`
? `&bindings=${JSON.stringify(script.bindings ?? {})}`
: ``
const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${bindingsQuery}${resourceQuery}`
templateRequest = stringifyRequest(src + query)
3 changes: 2 additions & 1 deletion src/pitcher.ts
Original file line number Diff line number Diff line change
@@ -68,7 +68,8 @@ export const pitch = function () {
const beforeLoaders = loaders.slice(cssLoaderIndex + 1)
return genProxyModule(
[...afterLoaders, stylePostLoaderPath, ...beforeLoaders],
context
context,
!! query.module
)
}
}
94 changes: 94 additions & 0 deletions test/advanced.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { SourceMapConsumer } from 'source-map'
import { fs as mfs } from 'memfs'
import { bundle, mockBundleAndRun } from './utils'

test('support chaining with other loaders', async () => {
const { componentModule } = await mockBundleAndRun({
entry: 'basic.vue',
modify: (config) => {
config!.module!.rules[0] = {
test: /\.vue$/,
use: ['vue-loader', require.resolve('./mock-loaders/js')],
}
},
})

expect(componentModule.data().msg).toBe('Changed!')
})

test.skip('inherit queries on files', async () => {
const { componentModule } = await mockBundleAndRun({
entry: 'basic.vue?change',
modify: (config) => {
config!.module!.rules[0] = {
test: /\.vue$/,
use: ['vue-loader', require.resolve('./mock-loaders/query')],
}
},
})

expect(componentModule.data().msg).toBe('Changed!')
})

test('expose file path as __file outside production', async () => {
const { componentModule } = await mockBundleAndRun({
entry: 'basic.vue',
})

expect(componentModule.__file).toBe('test/fixtures/basic.vue')
})

test('no __file in production when exposeFilename disabled', async () => {
const { componentModule } = await mockBundleAndRun({
mode: 'production',
entry: 'basic.vue',
})

expect(componentModule.__file).toBe(undefined)
})

test('expose file basename as __file in production when exposeFilename enabled', async () => {
const { componentModule } = await mockBundleAndRun({
mode: 'production',
entry: 'basic.vue',
vue: {
exposeFilename: true,
},
})
expect(componentModule.__file).toBe('basic.vue')
})

test.skip('source map', async () => {
const { code } = await bundle({
entry: 'basic.vue',
devtool: 'source-map',
})
const map = mfs.readFileSync('/test.build.js.map', 'utf-8')
const smc = new SourceMapConsumer(JSON.parse(map as string))
let line = 0
let col = 0
const targetRE = /^\s+msg: 'Hello from Component A!'/
code.split(/\r?\n/g).some((l, i) => {
if (targetRE.test(l)) {
line = i + 1
col = 0
return true
}
})
const pos = smc.originalPositionFor({
line: line,
column: col,
})
expect(pos.source.indexOf('basic.vue') > -1)
expect(pos.line).toBe(9)
})

test.todo('extract CSS')

test.todo('extract CSS with code spliting')

test.todo('support rules with oneOf')

test.todo('should work with eslint loader')

test.todo('multiple rule definitions')
103 changes: 99 additions & 4 deletions test/core.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mockBundleAndRun, normalizeNewline } from './utils'
import { mockBundleAndRun, normalizeNewline, genId } from './utils'

test('basic', async () => {
const { window, instance, componentModule } = await mockBundleAndRun({
@@ -61,14 +61,109 @@ test('pre-processors', async () => {
expect(componentModule.data().msg).toContain('Hello from Babel')

// style
const style = window.document.querySelector('style')!.textContent!
const style = normalizeNewline(
window.document.querySelector('style')!.textContent!
)
expect(style).toContain(
'body {\n font: 100% Helvetica, sans-serif;\n color: #999;\n}'
)
})

test('script setup', async () => {
await mockBundleAndRun({ entry: 'ScriptSetup.vue' })
test('style import', async () => {
const { window } = await mockBundleAndRun({
entry: 'style-import.vue',
})

const styles = window.document.querySelectorAll('style')
expect(styles[0].textContent).toContain('h1 { color: red;\n}')

// import with scoped
const id = 'data-v-' + genId('style-import.vue')
expect(styles[1].textContent).toContain('h1[' + id + '] { color: green;\n}')
})

test('style import for a same file twice', async () => {
const { window } = await mockBundleAndRun({
entry: 'style-import-twice.vue',
})

const styles = window.document.querySelectorAll('style')
expect(styles.length).toBe(3)
expect(styles[0].textContent).toContain('h1 { color: red;\n}')

// import with scoped
const id = 'data-v-' + genId('style-import-twice-sub.vue')
expect(styles[1].textContent).toContain('h1[' + id + '] { color: green;\n}')
const id2 = 'data-v-' + genId('style-import-twice.vue')
expect(styles[2].textContent).toContain('h1[' + id2 + '] { color: green;\n}')
})

test('template import', async () => {
const { instance } = await mockBundleAndRun({
entry: 'template-import.vue',
})

const el: Element = instance.$el
// '<div><h1>hello</h1></div>'
expect(el.children[0].tagName).toBe('H1')
expect(el.children[0].textContent).toBe('hello')
})

test('template import with pre-processors', async () => {
const { instance } = await mockBundleAndRun({
entry: 'template-import-pre.vue',
module: {
rules: [
{
test: /\.pug$/,
loader: 'pug-plain-loader',
},
],
},
})

const el: Element = instance.$el
// '<div><h1>hello</h1></div>'
expect(el.children[0].tagName).toBe('H1')
expect(el.children[0].textContent).toBe('hello')
})

test('script import', async () => {
const { componentModule } = await mockBundleAndRun({
entry: 'script-import.vue',
})
expect(componentModule.data().msg).toContain('Hello from Component A!')
})

// #1620
test('cloned rules should not intefere with each other', async () => {
await mockBundleAndRun({
entry: 'basic.vue',
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {},
},
],
},
{
test: /\.some-random-extension$/,
use: [
{
loader: 'css-loader',
options: {
url: true,
},
},
],
},
],
},
})
})

test('without script block', async () => {
100 changes: 100 additions & 0 deletions test/custom.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import * as path from 'path'
import { bundle, mockBundleAndRun } from './utils'

test('add custom blocks to the webpack output', async () => {
const { code } = await bundle({
entry: 'custom-language.vue',
module: {
rules: [
{
test: /\.js/,
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
],
},
})

// should also be transpiled
expect(code).toContain(
`
describe('example', function () {
it('basic', function (done) {
done();
});
});
`.trim()
)
})

test('custom blocks should work with src imports', async () => {
const { code } = await bundle({
entry: 'custom-import.vue',
module: {
rules: [
{
test: /\.js/,
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
],
},
})

expect(code).toContain(
`
describe('example', function () {
it('basic', function (done) {
done();
});
});
`.trim()
)
})

test('passes Component to custom block loaders', async () => {
const { componentModule } = await mockBundleAndRun({
entry: 'custom-language.vue',
module: {
rules: [
{
resourceQuery: /blockType=documentation/,
loader: require.resolve('./mock-loaders/docs'),
},
],
},
})

expect(componentModule.__docs).toContain(
'This is example documentation for a component.'
)
})

test('custom blocks can be ignored', async () => {
const { code } = await bundle({
entry: 'custom-language.vue',
})
expect(code).not.toContain(`describe('example'`)
})

test('custom blocks can be ignored even if cache-loader processes them', async () => {
const { code } = await bundle({
entry: 'custom-language.vue',
module: {
rules: [
{
test: /.vue$/,
loader: 'cache-loader',
options: {
cacheDirectory: path.resolve(__dirname, '.cache'),
},
},
],
},
})
expect(code).not.toContain(`describe('example'`)
})
Loading